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 }
AC代码

除此之外还有两种四维状态的DP,一种是f[l][r][k][a]表示把l到r这一段区间消除至只剩a(左/右)端的k个珠子的最小代价。

还有一种是f[l][r][k][s]表示把l到r这一段区间消除至只剩k个s颜色的珠子的最小代价。

写起来比较长,但是应该是比正解好想很多的。我没写,就不贴代码了。

以上是关于SPOJ6340 ZUMA - ZUMA的主要内容,如果未能解决你的问题,请参考以下文章

Zuma (区间DP)

Tsinghua OJ Zuma

LeetCode - Zuma Game

bzoj 1032: [JSOI2007]祖码Zuma

区间DPB. Zuma

区间DPB. Zuma