习题:Vasya and Binary String(DP)

题目

传送门

思路

题目不保证\(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;
}

猜你喜欢

转载自www.cnblogs.com/loney-s/p/13395732.html
今日推荐