zoukankan      html  css  js  c++  java
  • 【SCOI2008】着色方案

    有n个木块排成一行,从左到右依次编号为1~n。你有k种颜色的油漆,其中第i 种颜色的油漆足够涂ci 个木块。所有油漆刚好足够涂满所有木块,即 c1+c2+...+ck=n。相邻两个木块涂相同色显得很难看,所以你希望统计任意两个相邻木块颜色不同的着色方案。

    Input

    第一行为一个正整数k,第二行包含k个整数c1, c2, ... , ck。

    Output

    输出一个整数,即方案总数模1,000,000,007的结果。

    Sample Input

    样例1: 

    1 2 3 
    样例2: 

    2 2 2 2 2 
    样例3: 
    10 
    1 1 2 2 3 3 4 4 5 5

    题解:
    这个题目我们可以试着用记忆化搜索,状态设置的十分巧妙,首先我们可以看到ci是小于等于5的吧,并且只要数量一样,
    那么颜色对答案的贡献其实就是一样的,所有’我们可以定义一个五维的数组F[a1][a2][a3][a4][a5][h]表示数量为1的颜料数是
    a1,数量为2的颜色的颜色数为a2.......的最大方案数,然后转移的话看我代码吧,转移时要注意,最后一位是存上一次决策,
    如果上个决策是用剩余数为4的颜色,那么显然剩余数为3的颜色有一种是从4转移的,此时再用这种颜色就会染上相同的颜色。
    注意一下就好了。
    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<cstring>
    #define ll long long
    const int MOD=1000000007;
    using namespace std;
    int num[6];
    ll f[16][16][16][16][16][6];
    ll dp(int a1,int a2,int a3,int a4,int a5,int last){
      ll now=0;
      if((a1 | a2 | a3 | a4 | a5)==0) return f[a1][a2][a3][a4][a5][last]=1;
      if(f[a1][a2][a3][a4][a5][last]) return f[a1][a2][a3][a4][a5][last];
      if(a1) now+=(a1-(last==2))*dp(a1-1,a2,a3,a4,a5,1);now%=MOD;
      if(a2) now+=(a2-(last==3))*dp(a1+1,a2-1,a3,a4,a5,2);now%=MOD;
      if(a3) now+=(a3-(last==4))*dp(a1,a2+1,a3-1,a4,a5,3);now%=MOD;
      if(a4) now+=(a4-(last==5))*dp(a1,a2,a3+1,a4-1,a5,4);now%=MOD;
      if(a5) now+=a5*dp(a1,a2,a3,a4+1,a5-1,5);now%=MOD;
      f[a1][a2][a3][a4][a5][last]=now;now%=MOD;
      return now;
    }
    int main(){
      int n;
      memset(f,0,sizeof(f));
      scanf("%d",&n);
      for(int i=1;i<=n;i++){int x;scanf("%d",&x);num[x]++;}
      printf("%lld",dp(num[1],num[2],num[3],num[4],num[5],0));
      return 0;
    }
  • 相关阅读:
    mysql调优
    面试、。。。。
    StringBuffer 和 StringBuilder 的 3 个区别
    msql查询指定日期
    Windows 路由跟踪
    Xdebug配置
    ONVIF流媒体播放流程
    Windows 8 SP1 安装StockTrader 6.1
    使用log4c问题
    xcode插件安装
  • 原文地址:https://www.cnblogs.com/renjianshige/p/7128109.html
Copyright © 2011-2022 走看看