附上题目网址:https://www.luogu.org/problemnew/show/P2476
想法:
看数据范围,发现Ci最高才能达到5所以可以进行搜索,又因为有些是一样的所以再存一个last表示上一个涂的颜色,实现记忆化
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 inline long long read() 7 { 8 long long f=1,ans=0;char c; 9 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 10 while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} 11 return f*ans; 12 } 13 long long n,t[6],dp[16][16][16][16][16][6];//t是存能涂i下的数量,dp:注意到题目中的信息 1≤ci≤5 ,同时 相同的油漆本质上是相同的,于是我们令 f[c1][c2][c3][c4][c5][last] 表示当还能够涂 1 个格子的油漆有 c1 种,还能够涂 2 个格子的油漆有 c2 种……(以此类推)且按木块 1 ~ 那 编号顺序涂,上一次涂的是能够涂 last 个格子的油漆时的总方案数。 14 long long dfs(long long x1,long long x2,long long x3,long long x4,long long x5,long long last)//记忆化搜索 15 { 16 if(dp[x1][x2][x3][x4][x5][last]!=0) return dp[x1][x2][x3][x4][x5][last];//当搜到第二遍的时候,直接返回 17 if(x1+x2+x3+x4+x5==0) return 1;//当他们都没有的时候,没法再涂的时候,数量为1 18 long long ans=0; 19 if(x1!=0) ans+=(x1-(last==2))*dfs(x1-1,x2,x3,x4,x5,1);//回到我们所说的相邻情况,假设上一次用的是可以涂 last 个格子的油漆,那么上一次用完后,那种油漆就只可以涂 last−1 个格子了,那么这一次涂油漆的时候就不能再选可以涂 last−1 个格子的油漆的一种,因为这种上次已经用过了,且相同的油漆不能相邻。 20 if(x2!=0) ans+=(x2-(last==3))*dfs(x1+1,x2-1,x3,x4,x5,2); 21 if(x3!=0) ans+=(x3-(last==4))*dfs(x1,x2+1,x3-1,x4,x5,3); 22 if(x4!=0) ans+=(x4-(last==5))*dfs(x1,x2,x3+1,x4-1,x5,4); 23 if(x5!=0) ans+=x5*dfs(x1,x2,x3,x4+1,x5-1,5); 24 dp[x1][x2][x3][x4][x5][last]=ans%1000000007;//mod 25 return dp[x1][x2][x3][x4][x5][last];//返回数量 26 } 27 int main() 28 { 29 n=read(); 30 for(long long i=1;i<=n;i++) 31 { 32 long long x=read(); 33 t[x]++; 34 } 35 cout<<dfs(t[1],t[2],t[3],t[4],t[5],0); 36 }