题目链接
题目大意:
给定一个字符串,每个字符有自己的权值,可以对字符串进行操作,每次操作可以删除一个字符,花费就是这个字符的权值,问在保证没有子序列“hard”存在的最小花费是多少?
解题思路:
动态规划,dp[i][sta]表示前i个字符串没有出现sta这个子序列的最小花费,sta共有四个值,0:“h”,1:“ha”,2:“har”,3:“hard”。
对于不是“hard”这四个字符的则对当前状态没有影响。
对于字符:
“h”:影响sta=0,这个是一定要删掉的。
“a”:影响sta=1,如果保留这个‘a’得保证前面没有“h”存在,如果删掉这个‘a’的得保证前面也没有“ha”存在的情况,这样才能保证到当前没有“ha”存在。
“r”:影响sta=2, 如果保留这个‘r’得保证前面没有“ha”存在,删掉这个‘r’则得保证前面也没有“har”存在,这样才能保证到当前没有“har”存在。
“d”:影响sta=3, 如果保留这个‘d’得保证没有前面没有“har”存在,删掉这个‘d’则得保证前面也没有“hard”存在,这样才能保证到当前没有“hard”存在。
最后的答案就是dp[n][3]。
解题代码:
#include<bits/stdc++.h>
using namespace std;
mt19937 rng_32(chrono::steady_clock::now().time_since_epoch().count());
typedef long long ll;
const int maxn=1e5+10;
ll dp[maxn][4];
char s[maxn];
ll a[maxn];
int main()
{
int n;
scanf("%d",&n);
scanf("%s",s+1);
for (int i=1;i<=n;i++)
scanf("%I64d",&a[i]);
for (int i=1;i<=n;i++)
{
for (int j=0;j<4;j++)
dp[i][j]=dp[i-1][j];
if (s[i]=='h')
dp[i][0]=dp[i-1][0]+a[i];
else if (s[i]=='a')
dp[i][1]=min(dp[i-1][0],dp[i-1][1]+a[i]);
else if (s[i]=='r')
dp[i][2]=min(dp[i-1][1],dp[i-1][2]+a[i]);
else if (s[i]=='d')
dp[i][3]=min(dp[i-1][2],dp[i-1][3]+a[i]);
}
cout<<dp[n][3];
return 0;
}