1079: [SCOI2008]着色方案
题目:传送门
题解:
DP刚神多年前讲过的一道神题。
二话不说,上来就是一个六维数组:F[i][a][b][c][d][e]//表示上一次涂的颜色是还剩下i次可用的,a~e表示不同次数的颜色种数。
次数一样的颜色其实是相同的
那么我们记忆化搜索一下就OK(表示很久没打过了...)
代码(巨丑勿喷):
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 const int mod=1000000007; 8 typedef long long LL; 9 LL f[6][16][16][16][16][16];//f[i][a][b][c][d][e]表示上一次涂的颜色是还剩下i次可用的,a~e表示不同次数的颜色种数 10 int a[6]; 11 int k; 12 LL DP(int last,int a1,int a2,int a3,int a4,int a5) 13 { 14 if(a1<0 || a2<0 || a3<0 || a4<0 || a5<0)return 0; 15 if(a1==0 && a2==0 && a3==0 && a4==0 && a5==0)return 1; 16 if(f[last][a1][a2][a3][a4][a5]!=0) return f[last][a1][a2][a3][a4][a5]; 17 18 LL sum=0; 19 sum=( sum + ( ( a1 - ( ( last==2 ) ? 1 : 0 ) ) * DP ( 1,a1-1,a2,a3,a4,a5 ) ) ) % mod; 20 sum=( sum + ( ( a2 - ( ( last==3 ) ? 1 : 0 ) ) * DP ( 2,a1+1,a2-1,a3,a4,a5) )) % mod; 21 sum=( sum + ( ( a3 - ( ( last==4 ) ? 1 : 0 ) ) * DP ( 3,a1,a2+1,a3-1,a4,a5) )) % mod; 22 sum=( sum + ( ( a4 - ( ( last==5 ) ? 1 : 0 ) ) * DP ( 4,a1,a2,a3+1,a4-1,a5) )) % mod; 23 sum=( sum + a5*DP(5,a1,a2,a3,a4+1,a5-1))%mod; 24 f[last][a1][a2][a3][a4][a5]=sum; 25 return sum; 26 } 27 int main() 28 { 29 memset(f,0,sizeof(f)); 30 scanf("%d",&k); 31 for(int i=1;i<=k;i++) 32 { 33 int x; 34 scanf("%d",&x); 35 a[x]++; 36 } 37 printf("%lld\n",DP(0,a[1],a[2],a[3],a[4],a[5])); 38 return 0; 39 }