「UVA10559」Blocks

传送门
Luogu

解题思路

考虑区间 ( ext{DP})
(f[i][j][k]) 表示 ([i,j]) 这段区间接上后面 (k) 个与 (j) 颜色相同的块得到的答案。
转移就是:
(f[i][j][k] = maxleft{f[i][j][0]+(k+1)^2 ight})
(f[i][j][k] = maxleft{f[i][p][k+1]+f[p+1][j-1][0] ight}(pin[i, j] ext{且}c_p=c_j))
第一个方程就是把后面那一坨一起消掉,再消掉前面。
第二个方程就是在中间找一个与 (j) 颜色相同的点 (p) ,把 ([p+1,j-1]) 这段先消掉,然后让剩下的两坨拼起来再消。
写成记搜很方便的说

细节注意事项

  • 咕咕咕

参考代码

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <ctime>
#define rg register
using namespace std;
template < typename T > inline void read(T& s) {
 	s = 0; int f = 0; char c = getchar();
 	while (!isdigit(c)) f |= (c == '-'), c = getchar();
 	while (isdigit(c)) s = s * 10 + (c ^ 48), c = getchar();
 	s = f ? -s : s;
}

const int _ = 202;

int n, a[_], f[_][_][_], pre[_], las[_];

inline int dfs(int i, int j, int k) {
	if (i > j) return 0;
	if (f[i][j][k]) return f[i][j][k];
	f[i][j][k] = max(f[i][j][k], dfs(i, j - 1, 0) + (k + 1) * (k + 1));
	for (rg int p = pre[j]; p >= i; p = pre[p])
		f[i][j][k] = max(f[i][j][k], dfs(i, p, k + 1) + dfs(p + 1, j - 1, 0));
	return f[i][j][k];
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("in.in", "r", stdin);
#endif
	int T; read(T);
	for (rg int o = 1; o <= T; ++o) {
		memset(f, 0, sizeof f);
		memset(pre, 0, sizeof pre);
		memset(las, 0, sizeof las);
		read(n);
		for (rg int i = 1; i <= n; ++i) read(a[i]);
		for (rg int i = 1; i <= n; ++i) pre[i] = las[a[i]], las[a[i]] = i;
		printf("Case %d: %d
", o, dfs(1, n, 0));
	}
	return 0;
}

完结撒花 (qwq)

原文地址:https://www.cnblogs.com/zsbzsb/p/11746537.html