SPOJ6340 ZUMA - ZUMA
Posted huyufeifei
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPOJ6340 ZUMA - ZUMA相关的知识,希望对你有一定的参考价值。
题意:n个珠子排成一排,都有各自的颜色。
你可以选择不少于w个连续同色的珠子消掉,也可以先放着。你还可以任意插入任意颜色的珠子。
求全部消掉至少要插入几个珠子。
解:
什么毒瘤东西......
有个十分难受的DP。状态表示是f[l][r][k]表示在[l, r]这一段,l的左边有额外的k个与l同色的珠子时,把它们全部消去的最少代价。
转移也过于毒瘤。首先有
if k == w - 1 f[l][r][k] = f[l + 1][r][0] else f[l][r][k] = f[l][r][k + 1] + 1
然后然后还要考虑两段拼起来的情况,就是我们从中间选一段消去。
if(color i == l) f[l][r][k] = f[l + 1][i - 1][0] + f[i][r][k + 1]
这样我们就可以保证正确性了。写成记忆化搜索不用考虑转移顺序。代码十分之短.....
需要注意的是不能把相连的一段同色珠子合并,这样不一定是最优解。(??)
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 const int N = 110, INF = 0x3f3f3f3f; 6 7 int f[N][N][N], n, a[N], w; 8 int sum[N], col[N], top; 9 10 int solve(int l, int r, int k) { 11 //printf("%d %d %d ", l, r, k); 12 if(f[l][r][k] != -1) { 13 return f[l][r][k]; 14 } 15 if(r < l) { 16 return 0; 17 } 18 19 int ans = INF; 20 if(k + 1 >= w) { 21 ans = solve(l + 1, r, 0); 22 } 23 else { 24 ans = solve(l, r, k + 1) + 1; 25 } 26 for(int i = l + 1; i <= r; i++) { 27 if(col[l] == col[i]) { // [l + 1, i - 1] [i, r] 28 ans = std::min(ans, solve(l + 1, i - 1, 0) + solve(i, r, k + 1)); 29 } 30 } 31 return f[l][r][k] = ans; 32 } 33 34 int main() { 35 memset(f, -1, sizeof(f)); 36 scanf("%d%d", &n, &w); 37 for(int i = 1; i <= n; i++) { 38 scanf("%d", &col[i]); 39 } 40 41 int ans = solve(1, n, 0); 42 printf("%d", ans); 43 44 return 0; 45 }
除此之外还有两种四维状态的DP,一种是f[l][r][k][a]表示把l到r这一段区间消除至只剩a(左/右)端的k个珠子的最小代价。
还有一种是f[l][r][k][s]表示把l到r这一段区间消除至只剩k个s颜色的珠子的最小代价。
写起来比较长,但是应该是比正解好想很多的。我没写,就不贴代码了。
以上是关于SPOJ6340 ZUMA - ZUMA的主要内容,如果未能解决你的问题,请参考以下文章