🔎 🔎 🔎
(1)计算删长为n的某段的最大收益(背包)
(2)就变成了这个题
#define int ll
int a[222],cnt[222],val[222];
int dp[222][222][222];
//消除i到j及j后面k个与j颜色相同的块的最大收益
void init(int n)//贪心计算连续删除一段的最大收益
{
for(int i=1;i<=n;++i)
for(int j=i;j<=n;++j)
val[j]=max(val[j],val[j-i]+val[i]);
}
int dfs(int l,int r,int k)
{
if(l>r) return 0;
if(l==r) return dp[l][r][k]=val[cnt[l]+k];
if(dp[l][r][k]) return dp[l][r][k];
//第一种方案,最后一个位置和后面的k个一起消除,中间不留空
dp[l][r][k]=dfs(l,r-1,0)+val[cnt[r]+k];
//第二种方案,最后一个位置和前面某位置一起消除,中间空出一段一起消除
for(int i=l;i<r;++i)
{
if(a[i]!=a[r]) continue;
dp[l][r][k]=max(dp[l][r][k],dfs(l,i,cnt[r]+k)+dfs(i+1,r-1,0));
}
return dp[l][r][k];
}
void solve()
{
int n;cin>>n;
string s;cin>>s;
rpp(i,n) cin>>val[i];
init(n);
int pos=0;
char pre='2';
for(auto x:s)
{
if(x!=pre) ++pos;
a[pos]=x-'0';
++cnt[pos];
pre=x;
}
n=pos;
cout<<dfs(1,n,0)<<endl;
}