[CF1107E]Vasya and Binary String【区间DP】

题目描述

Vasya has a string s of length n consisting only of digits 0 and 1. Also he has an array a of length n.
Vasya performs the following operation until the string becomes empty: choose some consecutive substring of equal characters, erase it from the string and glue together the remaining parts (any of them can be empty). For example, if he erases substring 111 from string 111110 he will get the string 110. Vasya gets ax points for erasing substring of length x.
Vasya wants to maximize his total points, so help him with this!
{题目从CF盗取)

题目大意

给你一个长度为n(1<=n<=100)的01串s,从s中删除一段连续的长度为i的所有字符都相同的子串将会得到ai的分数,如果执行上述操作直到s被删除完,求最大分数和。
(题意从lg盗取)

题解

一道简单的区间DP,也不清楚为什么在洛谷上是一道黑题,可能是我太菜了。(废话不多说)
\(f[i][j][k]\)表示消除了\([j,k]\)后,在\(j\)之前有\(i\)个字符和\(j\)相同的消除的最大值。
考虑初始值,一开始\(f[i][L][R]=a[i+1]+f[0][L][R]\)\(L,R\)是当前的区间,(从0开始标号)
转移:\(f[k][L][R]=max(f[k][L][R],f[0][L+1][l-1]+f[k+1][l][R])\)(L和R是当前的区间)

ac代码

# include <bits/stdc++.h>
# define LL long long
using namespace std;
inline int gi(){
    int w=0,x=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return w?-x:x;
}
# define N 105
LL f[N][N][N];
int a[N],n,m;
char s[N];
int main(){
    n=gi();
    scanf("%s",s);
    for (register int i=1;i<=n;i++) a[i]=gi();
    for (register int i=0;i<n;i++)
        for (register int j=0;j+i<n;j++)
            for (register int k=0;k<n;k++){
                f[k][j][j+i]=a[k+1]+f[0][j+1][j+i];
                for (register int l=j+1;l<=j+i;l++) 
                    if (s[j]==s[l]) 
                        f[k][j][j+i]=max(f[k][j][j+i],f[0][j+1][l-1]+f[k+1][l][j+i]);
            }
    printf("%lld\n",f[0][0][n-1]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/chhokmah/p/10577687.html