题目链接
思路:dp[i][j][len] 表示从i到j个大块,并且右边有长度为len的与第j个块颜色相同的块。
初始为dp[0][j][0]。
从右边开始考虑,也就是从第j个块开始考虑,
如果将第j个块直接消掉,结果为dp[i][j-1][0]+ (len[j]+len)*(len[j]+len)
如果考虑左边有一个颜色块k与第j块相同能与之合并,结果为dp[i][k][len[k]+len] + dp[k+1][j-1][0]
以上所有情况的最大值就是dp[i][j][k]
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <cmath>
#include <limits.h>
#include <iomanip>
#include <queue>
#include <cstring>
using namespace std;
typedef long long LL;
typedef vector<int> vec;
//#pragma GCC optimize(2)
struct node{
node(int _color, int _len):color(_color), len(_len) {}
int color;
int len;
};
static vector<node> V;
static int t;
static int n;
static int score[210][210][210];
int clickbox(int L, int R, int len){
if(score[L][R][len] != -1)
return score[L][R][len];
if(L == R)
return score[L][R][len] = (V[R].len+len)*(V[R].len+len);
int sorcemax = clickbox(L, R-1, 0) + (V[R].len+len)*(V[R].len+len);
for (int i = L; i < R; i++) {
if(V[i].color == V[R].color){
int cc = clickbox(L, i, V[R].len+len) + clickbox(i+1, R-1, 0);
sorcemax = max(sorcemax, cc);
}
}
return score[L][R][len] = sorcemax;
}
int main()
{
//freopen("E:\\Desktop\\data.txt", "r", stdin);
//ios::sync_with_stdio(false);
int co;
int pre = -1;
int xlen = 0;
int th = 1;
cin >> t;
while (t--) {
memset(score,0xff,sizeof(score));
V.clear();
xlen = 1;
pre = -1;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> co;
if(pre == -1){
pre = co;
}else {
if(pre == co)
xlen++;
else {
V.push_back(node(pre, xlen));
pre = co;
xlen = 1;
}
}
}
V.push_back(node(pre, xlen));
cout << "Case " << th++ << ": " << clickbox(0, V.size()-1, 0) << endl;
}
return 0;
}