传送门
思路:很容易想到这是一道区间DP的题,但是如何写区间DP方程,二维好像表示不了,那三维呢?好像也不好想,那就四维。
,表示区间中 u 字符连着消去 k 长度的最大价值( 只有两个字符,即 0和1 )
s 表示区间的一个点,如果
那么dp 转移方程
表示区间的最大价值
细节见代码:
///#include<bits/stdc++.h>
///#include<unordered_maps>
///#include<unordered_set>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<bitset>
#include<set>
#include<stack>
#include<map>
#include<list>
#include<new>
#include<vector>
#define MT(a, b) memset(a,b,sizeof(a));
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double pai = acos(-1.0);
const double E = 2.718281828459;
const ll mod = 10007;
const long long INF = 0x3f3f3f3f3f3f3f;
const int maxn = 1e7 + 5;
int n;
char x[105];
ll dp[105][105][105][2], ans[105][105];
ll value[105], pre[2][105];
int main() {
memset(pre, 0, sizeof(pre));
memset(dp, 0, sizeof(dp));
memset(ans, 0, sizeof(ans));
cin >> n >> x + 1;
for (int i = 1; i <= n; i++) {
cin >> value[i];
pre[0][i] = pre[0][i - 1];
pre[1][i] = pre[1][i - 1];
pre[x[i] - '0'][i]++;
}
for (int d = 1; d <= n; d++) { /// d = 长度
for (int i = 1; i + d - 1 <= n; i++) { /// i = 起点
int l = i, r = i + d - 1; /// l,r = 区间
for (int k = 1; k <= n; k++) { /// k = 需要区间字符重复的数量
for (int u = 0; u <= 1; u++) { /// u 重复的字符
int cnt = pre[u][r] - pre[u][l - 1];
if (cnt < k) { ///不存在的状态
dp[l][r][k][u] = -INF;
continue;
}
for (int s = l; s <= r; s++) { /// s = 区间的中点
if (x[s] == u + '0') {
if (s == r && k - 1 != 0) continue; ///不合理的上一个状态
dp[l][r][k][u] = max(ans[l][s - 1] + dp[s + 1][r][k - 1][u], dp[l][r][k][u]);
}
}
ans[l][r] = max(ans[l][r], dp[l][r][k][u] + value[k]);
}
}
}
}
cout << ans[1][n] << endl;
return 0;
}