【BZOJ1079】着色方案

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1079


 

吼题啊!

自己做,不会做,看完题解分析,不会写代码,看完代码自己写,交上去报错,复制题解代码交上去,通过。

类似于中国象棋,这道题也涉及合并本质相同的状态。最简单的思路是,设dp[a1][a2]...[ak][last]表示第几种颜色还剩几次可以使用,上一次用的是什么颜色的方案数。显然会炸,实际上,我们只关心还可以用几次的颜色有几种,并不关心具体是哪种颜色,刚好,每种颜色可以使用的次数并不多。设dp[a][b][c][d][e][l]表示还可用1次的颜色有a种,2次的有b种,...,上一次用的是剩余l次的颜色,注意是上一次用之前剩l次,对于当前是剩l-1次的某种颜色。然后讨论接下来选择剩几次的颜色即可,注意剩l+1次的颜色会少一种选择。

 1 #include <cstdio>
 2 #include <cstring>
 3 
 4 typedef long long ll;
 5 
 6 const int maxk = 16, maxc = 6, mod = 1e9 + 7;
 7 
 8 int rest[maxc];
 9 ll dp[maxk][maxk][maxk][maxk][maxk][maxc];
10 
11 ll dfs(int a, int b, int c, int d, int e, int l) {
12     ll& f = dp[a][b][c][d][e][l];
13     if (f != -1) return f;
14     if (a + b + c + d + e == 0) return 1;
15     ll t = 0;
16     if (a) t += (a - (l == 2)) * dfs(a - 1, b, c, d, e, 1);
17     if (b) t += (b - (l == 3)) * dfs(a + 1, b - 1, c, d, e, 2);
18     if (c) t += (c - (l == 4)) * dfs(a, b + 1, c - 1, d, e, 3);
19     if (d) t += (d - (l == 5)) * dfs(a, b, c + 1, d - 1, e, 4);
20     if (e) t += e * dfs(a, b, c, d + 1, e - 1, 5);
21     return f = t % mod;
22 }
23 
24 int main() {
25     int k, c;
26     scanf("%d", &k);
27     for (int i = 1; i <= k; ++i) {
28         scanf("%d", &c);
29         ++rest[c];
30     }
31     memset(dp, -1, sizeof(dp));
32     printf("%lld", dfs(rest[1], rest[2], rest[3], rest[4], rest[5], 0));
33     return 0;
34 }
AC代码

 

posted @ 2018-11-02 07:45  Mr^Kevin  阅读(...)  评论(... 编辑 收藏