BZOJ 1079 [SCOI2008]着色方案

http://www.lydsy.com/JudgeOnline/problem.php?id=1079

思路:如果把每种油漆看成一种状态,O(5^15)不行

DP[a][b][c][d][e][f]:a表示能凃一个的有多少个

b能凃2个的还有多少个

c能凃3个的还有多少个

d能凃4个的还有多少个

e能凃5个的还有多少个

last 上次凃的是:last个油漆。

所以这次如果选last-1个油漆的时候,数量还要减一,与上次不同

 1 //#pragma comment(linker, "/STACK:167772160")
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <iostream>
 6 #include <queue>
 7 #include <stack>
 8 #include <cmath>
 9 #include <set>
10 #include <utility>
11 #include <algorithm>
12 #include <vector>
13 #include <map>
14 // #include<malloc.h>
15 using namespace std;
16 #define clc(a,b) memset(a,b,sizeof(a))
17 #define LL long long
18 void fre() { freopen("in.txt","r",stdin);}
19 const int inf = 0x3f3f3f3f;
20 const double eps = 1e-5;
21 // const double pi = acos(-1);
22 const LL mod = 1e9+7;
23 inline int r(){
24     int x=0,f=1;char ch=getchar();
25     while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();}
26     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
27     return x*f;
28 }
29 int A[16];
30 LL dp[16][16][16][16][16][6];
31 bool vis[16][16][16][16][16][6];
32  
33 LL work(int a,int b,int c,int d,int e,int last){
34     LL tem;
35     tem=0; 
36     if((a|b|c|d|e)==0) return 1;
37     if(vis[a][b][c][d][e][last]) return dp[a][b][c][d][e][last];
38     if(a)  
39        tem+=(a-(last==2))*work(a-1,b,c,d,e,1);
40     if(b)
41         tem+=(b-(last==3))*work(a+1,b-1,c,d,e,2);
42     if(c)
43         tem+=(c-(last==4))*work(a,b+1,c-1,d,e,3);
44     if(d)
45         tem+=(d-(last==5))*work(a,b,c+1,d-1,e,4);
46     if(e)
47         tem+=e*work(a,b,c,d+1,e-1,5);
48     dp[a][b][c][d][e][last]=(tem%mod);
49     vis[a][b][c][d][e][last]=true;
50     return dp[a][b][c][d][e][last];
51 }
52  
53 int main(){
54        // fre();
55    int n;
56    while(~scanf("%d",&n)){
57       // clc(dp,0);
58       // clc(vis,0);
59       // clc(A,0);
60       for(int i=0;i<n;i++){
61          int x;
62          x=r();
63          A[x]++;
64       }
65       LL ans;
66       ans=work(A[1],A[2],A[3],A[4],A[5],0);
67       cout<<ans<<endl;
68    }
69     return 0;
70 }
原文地址:https://www.cnblogs.com/ITUPC/p/5546566.html