UVA - 10559 Blocks
思路:区间dp + 记忆化搜索
dp[i][j][k] : (区间 [i, j] 后面带上一段和 j 颜色相同的且长度为 k )的消消乐最大积分
1.消最后一段颜色和 j 颜色相同的
dp[i][j][k] <-- dp[i][j-1][0] + (k+1)^2
2.对于i <= l < j, 如果 l 和 j 的颜色相同, 那么可以把 [l+1, j-1]消掉, 那么剩下的一段就有 k+1 个和 l 相同的一段了
dp[i][j][k] <-- dp[i][l][k+1] + dp[l+1][j-1][0]
答案就是dp[1][n][0],采用记忆化搜索更方便转移
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define fi first #define se second #define y1 y11 #define pi acos(-1.0) #define LL long long //#define mp make_pair #define DEBUG #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<long double, long double> #define mem(a, b) memset(a, b, sizeof(a)) #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout); //head const int N = 205; int dp[N][N][N]; int a[N]; int dfs(int l, int r, int k) { if(l > r) return 0; if(l == r) return (k+1)*(k+1); if(~dp[l][r][k]) return dp[l][r][k]; dp[l][r][k] = dfs(l, r-1, 0) + (k+1)*(k+1); for (int i = l; i < r; i++) { if(a[i] == a[r]) { dp[l][r][k] = max(dp[l][r][k], dfs(l, i, k+1) + dfs(i+1, r-1, 0)); } } return dp[l][r][k]; } int main() { int T, n; scanf("%d", &T); for(int cs = 1; cs <= T; cs++) { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); mem(dp, -1); printf("Case %d: %d\n", cs, dfs(1, n, 0)); } return 0; }