1. 程式人生 > >【BZOJ1079】著色方案

【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程式碼