Codeforces 1107E Vasya and Binary String
题目链接
http://codeforces.com/contest/1107/problem/E
题目大意
给你一个 $01$ 串,你可以每次选择一段连续 $k$ 个相同的数字将它们删除并获得权值 $a_k$ 。问能获得的最大权值为多少。
题目分析
定义 $f[l][r][x][t]$ 为区间 $[l, r]$ 被消成连续的 $x$ 个 $t$ 有最大的权值为多少,那么可以使用 $DP$ ,对于任意的 $x = 0$ 的情况,它可能是由 $f[l][r][y][t], (y \neq 0)$ 以及 $f[l][r][x][!t]$ 转移而来。而对于 $x \neq 0$ 的情况,它一定是一个长度为 $1$ 的区间加上一个长度为 $x – 1$ 的区间拼起来的。根据这些进行 $DP$ 即可。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
int n, m, t;
string str;
long long a[105];
long long f[105][105][105][2];
bool vis[105][105][105][2];
int read(){
int x;
scanf("%d", &x);
return x;
}
int dfs(int l, int r, int x, int t){
int i, j;
if(vis[l][r][x][t]){
return 0;
}
vis[l][r][x][t] = true;
if(x == 0){
for(i=1;i<=r-l+1;i++){
dfs(l, r, i, t);
if(f[l][r][i][t] != -1){
f[l][r][x][t] = max(f[l][r][x][t], f[l][r][i][t] + a[i]);
}
}
dfs(l, r, 0, !t);
f[l][r][x][t] = f[l][r][x][!t] = max(f[l][r][x][t], f[l][r][x][!t]);
}else{
for(i=l;i<r;i++){
dfs(l, i, 1, t);
dfs(i + 1, r, x - 1, t);
if(f[l][i][1][t] != -1 and f[i + 1][r][x - 1][t] != -1){
f[l][r][x][t] = max(f[l][r][x][t], f[l][i][1][t] + f[i + 1][r][x - 1][t]);
}
}
}
return 0;
}
int main(){
int i, j;
memset(f, -1, sizeof(f));
cin >> n;
cin >> str;
str = 'x' + str;
for(i=1;i<=n;i++){
cin >> a[i];
}
for(i=1;i<=n;i++){
f[i][i][1][str[i] - '0'] = 0;
vis[i][i][1][str[i] - '0'] = true;
}
dfs(1, n, 0, 0);
cout << f[1][n][0][0] << endl;
return 0;
}