Educational Codeforces Round 59 (Rated for Div. 2)E. Vasya and Binary String 区间dp

题目链接:E. Vasya and Binary String

与这道题相似

题意,给个长度为n的01字符串s,以及长度为n数组a.你每次可以选择任意长度L的连续子串(要求子串每个字符相同)从原串中去掉,并获得a【L】的值。问你可能获得的值最多是多少

题解:

dp[i][j][k]代表区间i,j后面跟k的与s[j]相同的字符。

状态转移

 第一种去掉j-1后面的k+1字符dp[l][r][k]=max(dp[l][r][k],dp[l][r-1][0]+a[k+1]);

 第二种在i,j-1的区间中找一个与s[j]相同的位置p然后去掉中间的部分[p+1,j-1]

  dp[i][j][k]=max(dp[i][j][k],dp[i][p][k+1]+dp[p+1][j-1][0]);

最后答案就是dp[0][n-1][0];

#include<bits/stdc++.h>
#define ws wewe
#define ll long long
using namespace std;
const int N=105;
ll a[N],dp[N][N][N];
int n;
string ss;
int main()
{

    scanf("%d",&n);
    cin>>ss;
    for(int i=1;i<=n;i++)scanf("%I64d",&a[i]);
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            dp[i][i][j]=a[j+1];
        }
    }
    for(int s=2;s<=n;s++)//枚举区间长度
    {
        for(int l=0;l+s-1<n;l++)//枚举区间左节点
        {
            int r=l+s-1;
            for(int k=0;k<n;k++)//枚举后面有多少个s[r]相同的字符
            {
                dp[l][r][k]=dp[l][r-1][0]+a[k+1];
                for(int j=l;j<r;j++)
                {
                    if(ss[j]==ss[r])
                    {
                         dp[l][r][k]=max(dp[l][r][k],dp[l][j][k+1]+dp[j+1][r-1][0]);
                    }

                }
            }
        }
    }
    printf("%I64d
",dp[0][n-1][0]);

    return 0;
}
原文地址:https://www.cnblogs.com/lhclqslove/p/10327287.html