CF1107E Vasya and Binary String
CF1107E Vasya and Binary String
f[l][r][t]表示将 [l,r] 和 (r,n]中颜色=a[r]的前t个 的消掉的最大收益(最后若干个a[r]颜色已经连续)
- 消掉后面的: f[l][r][t]<-f[l][r-1][0]+(b[r]+t)**2
- 将中间一段消掉使前面一个a[r]颜色的与之合并: f[l][r][t]<-f[l][k][b[r]+t]+f[k+1][r-1][0]其中l<=k<r
点击查看代码
#include <stdio.h>
#include <string.h>
const int N = 205;
int max(int x, int y) { return x < y ? y : x; }
int n, a[N], b[N], f[N][N][N];
int dfs(int l, int r, int t) {
if(~f[l][r][t]) return f[l][r][t];
int tmp = b[r] + t; // 最后一段的a[r]颜色的个数
if(l == r) f[l][r][t] = tmp * tmp; // 长度为1:合并
else {
f[l][r][t] = dfs(l, r - 1, 0) + tmp * tmp; // 使用所有的a[r]颜色
for(int k = l; k < r; k ++) // 将中间一段删掉以获得一段更长的a[r]颜色
if(a[k] == a[r]) f[l][r][t] = max(f[l][r][t], dfs(l, k, tmp) + dfs(k + 1, r - 1, 0));
}
return f[l][r][t];
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i ++) scanf("%d", a + i);
for(int i = 1; i <= n; i ++) scanf("%d", b + i);
memset(f, -1, sizeof(f)), printf("%d\n", dfs(1, n, 0));
return 0;
}
f[l][r][t] 表示 [l,r]; r右边还有 t 的与 r 相同颜色的
- 消掉 r: f[l][r][t] <- f[l][r-1][0] + a[t+1]
- 消掉中间若干: 设 k 与 r 同色 : f[l][r][t] <- f[l][k][t+1] + f[k+1][r-1][0] (消掉[k+1,r-1])
点击查看代码
#include <stdio.h>
#include <string.h>
#include <algorithm>
const int N = 105;
typedef long long LL;
int n, tot[N]; // tot表示i右边的同色的个数
char str[N]; LL a[N], f[N][N][N];
int main() {
scanf("%d%s", &n, str + 1);
for(int i = 1; i <= n; i ++) scanf("%lld", a + i); // 先更新一下 a
for(int i = 1; i <= n; i ++) for(int j = 1; j < i; j ++) a[i] = std::max(a[i], a[j] + a[i-j]);
for(int i = 1; i <= n; i ++) for(int j = i + 1; j <= n; j ++) tot[i] += str[i] == str[j];
for(int len = 1; len <= n; len ++)
for(int l = 1, r = len; r <= n; l ++, r ++) {
for(int t = 0; t <= tot[r]; t ++) {
f[l][r][t] = f[l][r-1][0] + a[t+1];
for(int k = l; k < r; k ++) if(str[k] == str[r])
f[l][r][t] = std::max(f[l][r][t], f[l][k][t+1] + f[k+1][r-1][0]);
}
}
printf("%lld\n", f[1][n][0]);
return 0;
}