区间dp
记 f[l][r][m] 表示方块 l ~ r 右边加上 m 个与方块 r 同色的方块的最大得分, a[i] 表示方块 i 的颜色
记 b[i] 表示 min(j) // j <= i && 方块 j ~ i 的颜色一样
讨论方块 r 的合并情况得出转移方程:
p = max(b[r], l);
1:直接消去 r ,转移到 f[l][r - 1][0] + (m+r-p+1)*(m+r-p+1)
2:枚举 q < p && a[i] == a[r],转移到 f[q+1][p-1][0] + f[l][q][m+r-p+1]
初始化:f[i][i][0] = 1
答案为:f[1][n][0]
1 #include<iostream> 2 #include<cstdio> 3 #include<fstream> 4 #include<algorithm> 5 #include<cmath> 6 #include<deque> 7 #include<vector> 8 #include<queue> 9 #include<string> 10 #include<cstring> 11 #include<map> 12 #include<stack> 13 #include<set> 14 using namespace std; 15 typedef long long LL; 16 17 inline int Read() { 18 int res = 0, f = 1; 19 char ch = getchar(); 20 while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); } 21 while(ch >= '0' && ch <= '9') { res = res*10 + ch - '0'; ch = getchar(); } 22 return res*f; 23 } 24 25 int T, n, a[205], f[205][205][205], b[205], kase; 26 27 int dp(int l, int r, int m) { 28 if(f[l][r][m] || r < l) return f[l][r][m]; 29 int p = max(b[r], l); 30 int& ans = f[l][r][m]; 31 ans = dp(l, p - 1, 0) + (r - p + 1 + m)*(r - p + 1 + m); 32 for(int q = l; q < p; q++) 33 if(a[q] == a[r] && a[q + 1] != a[r]) ans = max(ans, dp(l, q, m + r - p + 1) + dp(q + 1, p - 1, 0)); 34 return ans; 35 } 36 37 int main() { 38 T = Read(); 39 while(T--) { 40 n = Read(); 41 for(int i = 1; i <= n; i++) 42 a[i] = Read(); 43 for(int i = 1; i <= n; i++) { 44 int j = i - 1; 45 while(j && a[j] == a[j + 1]) 46 j--; 47 j++; 48 b[i] = j; 49 } 50 memset(f, 0, sizeof(f)); 51 for(int i = 1; i <= n; i++) 52 f[i][i][0] = 1; 53 printf("Case %d: %d\n", ++kase, dp(1, n, 0)); 54 } 55 return 0; 56 }