原题链接:https://vjudge.net/problem/UVA-10559
分类:动态规划
备注:多维考虑
dp[i][j][k]表示区间[i,j]块右接上k个与a[j]同色的元素
先将最右边同色的特意挑选出来,得到p ∈ [i, j]中最左边的使得a[p] = a[p+1] = … = a[j]的值,即从右边界j位置往左到p位置是同色的最长段。如果直接将[p,j]消除,则状态转移到d(i, p - 1, 0) + (j - p + 1 +k)^2
如果[i, p - 1]段中仍有与a[j]同色的段,可以找到q满足q<p且a[q] == a[j] && a[q + 1] != a[q],考虑将[q+1,p-1]这一段先消除掉,然后让[i,q]和[p,j]拼接起来,则最右边同色段会变长,即与a[j]同色的段有了增长。
这种情况要考虑对q的枚举,状态转移为d(q + 1, p - 1, 0) + d(i, q, j - p + 1 + k)
返回所有状态中最大值即可。
#include <bits/stdc++.h>
using namespace std;
int t, n, a[205], dp[205][205][205];
int d(int i, int j, int k) {
if (i > j) return 0;
if (dp[i][j][k]) return dp[i][j][k];
if (i == j) return dp[i][j][k] = (1 + k) * (1 + k);
int p = j;
while (p > i && a[p - 1] == a[j]) p--;
int ret = d(i, p - 1, 0) + (j - p + k + 1) * (j - p + k + 1);
for (int q = p - 1; q >= i; q--) {
if (a[q] == a[j] && a[q] != a[q + 1]) {
ret = max(ret, d(q + 1, p - 1, 0) + d(i, q, j - p + k + 1));
}
}
return dp[i][j][k] = ret;
}
int main(void) {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
scanf("%d", &t);
int kase = 0;
while (t--) {
scanf("%d", &n);
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
printf("Case %d: %d\n", ++kase, d(1, n, 0));
}
return 0;
}