D. Easy Problem dp(有衔接关系的dp(类似于分类讨论) )

D. Easy Problem dp(有衔接关系的dp(类似于分类讨论) )

题意

给出一个串 给出删除每一个字符的代价问使得串里面没有hard的子序列需要付出的最小代价(子序列不连续也行)

思路

要满足hard 先要满足har 要满足har 先要满足ha 一次类推
这类问题的一个共同点是要每个地方都要满足一系列前置条件才能成立也就是说有衔接关系
所以如果是构造问题 那么dp数组加一维已经满足了几个,如果是删除问题dp数组加一维 切断了哪一个即可
所以我们可以设置dp数学 dp[i][1,2,3,4] 表示在i位置时 字符是h,a,r,d 对应于 1,2,3,4使得以h,a,r,d为前缀不存在的所需要消耗的最小代价是多少

这样\(dp[i][1]=dp[i-1][1]+a[i]\) 表示要使得h不存在 有h就要删掉h
\(dp[i][2]=max(dp[i-1][1],dp[i-1][2]+a[i])\)要使得ha不存在 要么没有h 要么没有a
\(dp[i][3]=max(dp[i-1][2],dp[i-1][3]+a[i])\)要使得har成立 要么没有要么a 要么没有r
\(dp[i][4]=max(dp[[i-1][3],dp[i-1][4]+a[i])\)同上
注意 这里i可以用滚动数组滚掉节省空间 不然开不下 记得开long long

#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5+5;
#define int long long 
#define F first
#define S second
#define pb push_back
#define pii pair<int ,int >
#define mkp make_pair
const int inf=0x3f3f3f3f;
char s[maxn];
int a[maxn];
int dp[10];
int32_t main(){
    int n;
    scanf("%lld",&n);
    scanf("%s",s+1);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    for(int i=1;i<=n;i++){
        if(s[i]=='h')dp[1]=dp[1]+a[i];
        if(s[i]=='a')dp[2]=min(dp[1],dp[2]+a[i]);
        if(s[i]=='r')dp[3]=min(dp[2],dp[3]+a[i]);
        if(s[i]=='d')dp[4]=min(dp[3],dp[4]+a[i]);
    }
    cout<<dp[4]<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ttttttttrx/p/10800144.html
今日推荐