题目
思路
题目不保证\(a_i\)最优
所以我们先要用一个简单的背包来处理一下\(a_i\)
我们考虑到对于一个区间,我们不仅需要这个区间的\(l\)和\(r\),还要知道右边或者左边有多少个相同的连续的序列
我们设\(dp[i][j][k]\)为区间\(i\)到\(j\),有\(k\)个和\(a_j\)相同的数字
转移的话,我们就考虑将以j为右端点的某一个区间全部删除即可
同时也要考虑剩下\(i-(j-1)\)段的情况
总时间复杂度即为\(O(n^4)\),
但比较明显的一点,这个DP是跑不满的,
代码
#include<iostream>
#include<cstring>
using namespace std;
int n;
int a[105];
long long f[105];
//长度为i的最大代价
long long dp[105][105][105];
//区间为i~j,同时有k个和a[j]相同的数
char s[105];
long long solve(int l,int r,int k)
{
if(l>r)
return 0;
if(dp[l][r][k]!=-1)
return dp[l][r][k];
dp[l][r][k]=solve(l,r-1,0)+f[k+1];
for(int i=l;i<r;i++)
if(s[i]==s[r])
dp[l][r][k]=max(dp[l][r][k],solve(l,i,k+1)+solve(i+1,r-1,0));
return dp[l][r][k];
}
int main()
{
ios::sync_with_stdio(false);
memset(dp,-1,sizeof(dp));
cin>>n>>(s+1);
for(int i=1;i<=n;i++)
{
cin>>a[i];
f[i]=a[i];
}
for(int i=1;i<=n;i++)
for(int j=a[i];j<=n;j++)
f[j]=max(f[j],f[j-i]+a[i]);
cout<<solve(1,n,0);
return 0;
}