题目传送门
题目大意
有$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\n", ++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 }
原文地址:https://www.cnblogs.com/yyf0309/p/9918212.html
时间: 2024-10-13 17:16:11