CF1096D Easy Problem

题目传送门

题目大意

给你一个长为\(n\)的字符串\(s\)以及\(a_{1 \ldots n}\),删去第\(i\)个字符的代价为\(a_i\),你需要删去一些字符(如果一开始就符合条件当然可以不删)使得剩下的串中不含子序列 "\(hard\)"(子序列不需要连续),求最小代价

思路

典型的\(dp\)

定义状态:

\(f_{i,j}\)\(s\)字符串的前\(i\)个字符匹配到\(hard\)的第\(j\)个字母所花的最小代价

转移:

先看\(s_i\)等不等于\(hard\)的第\(j\)

如果不等于,则\(f_{i,j}=f_{i-1,j}\)

否则,就有两种选择:一种就是不继续去掉\(hard\)的第\(j\)位,一种就是继续去掉。这两者之间取\(min\),就是\(f_{i,j}\)了,所以\(f_{i,j}=min(f_{i-1,j-1},f_{i-1,j}+a_i)\)

注意

本题卡 \(long\) \(long\) ,需注意

代码

#include
using namespace std;
long long n,a[100001],f[100001][5],ans;
char s[100001],c[5]={' ','h','a','r','d'};
int main(){
    scanf("%lld",&n);
    for(int i=1;i<=n;i++) scanf(" %c",&s[i]);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    memset(f,0x7f7f7f7f,sizeof(f));
    for(int i=1;i<=4;i++) f[0][i]=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=4;j++){
            if(s[i]!=c[j]) f[i][j]=f[i-1][j];
            else f[i][j]=min(f[i-1][j-1],f[i-1][j]+a[i]);
        }
    }
    ans=min(f[n][1],min(f[n][2],min(f[n][3],f[n][4])));
    printf("%lld",ans);
    return 0;
}

不要忘记点个赞哦

完结撒花

你可能感兴趣的:(CF1096D Easy Problem)