UVa 10559 Blocks - 动态规划

Posted yyf0309

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVa 10559 Blocks - 动态规划相关的知识,希望对你有一定的参考价值。

题目传送门

  传送门

题目大意

  有$n$个方块排成一排,每次可以选择一段连续相同的颜色的方块消去并将两端拼接起来,设消去的长度为$x$,那么可以得到$x^2$的分数。问消去所有方块后的最高得分。

  标算的状态设计感觉比较神仙。

  设$f_{l, r, k}$表示考虑到第$l$个方块到第$r$个方块,在第$r$个方块后面有$k$个和第$r$个方块的颜色一样的方块,将这些方块都消去能够得到的最大的分数。

  首先不难发现每次消除一定消除的是当前一个极大颜色相同的连续段。

  转移的时候考虑$r$所在原序列的一个极大颜色相同的连续段。显然有两种决策:

  • 把它和后面的$k$的方块一起消掉。
  • 把它作为$[l, r]$某个子区间$[l, r‘]$的右边和$r‘$颜色相同的方块,然后将$r‘$的后一个方块到$r$所在原序列的一个极大颜色相同的连续段的第一个方块的前一个方块之间的方块(包含端点)先消去(这样使得$r‘$和$r$所在的那个连续段连接在一起)。

  时间复杂度$O(n^4)$。([一脸懵逼.gif])

Code

 1 /**
 2  * UVa
 3  * Problem#10559
 4  * Accepted
 5  * Time: 670ms
 6  */
 7 #include <iostream>
 8 #include <cstdlib>
 9 #include <cstring>
10 #include <cstdio>
11 using namespace std;
12 typedef bool boolean;
13 
14 const int N = 205;
15 
16 int n;
17 int a[N], f[N][N][N];
18 
19 inline void init() {
20     scanf("%d", &n);
21     for (int i = 1; i <= n; i++)
22         scanf("%d", a + i);
23 }
24 
25 int dp(int l, int r, int append) {
26     if (l > r)
27         return 0;
28     int& rt = f[l][r][append];
29     if (~rt)
30         return rt;
31     int cont = 1, k = r;
32     while (k > l && a[k - 1] == a[r])
33         k--, cont++;
34     rt = dp(l, k - 1, 0) + (cont + append) * (cont + append);
35     for (int i = l; i < k; i++)
36         if ((a[i + 1] != a[i]) && a[i] == a[k])
37             rt = max(rt, dp(l, i, append + cont) + dp(i + 1, k - 1, 0));
38     return rt;
39 }
40 
41 inline void solve() {
42     static int Kase = 0;
43     memset(f, -1, sizeof(f));
44     printf("Case %d: %d
", ++Kase, dp(1, n, 0));
45 }
46 
47 int T;
48 int main() {
49     scanf("%d", &T);
50     while (T--) {
51         init();
52         solve();
53     }
54     return 0;
55 }

以上是关于UVa 10559 Blocks - 动态规划的主要内容,如果未能解决你的问题,请参考以下文章

「UVA10559」Blocks

UVA - 10559 Blocks

luogu UVA10559 ybtoj 区间DP课堂过关 例题3消除木块 & 方块消除 Blocks

Uva10559Blocks(区间DP)

UVa 10559 Blocks (DP)

UVA10559 Blocks(区间dp)