题目链接:点击查看
题目大意:给出一个字符串,每个字符都有一个权值,现在需要删除权值和最少的字符,满足字符串中不再含有子序列“hard”
题目分析:线性dp,但我不会,看着题解写的,首先令dp[ i ][ 1 ]为到第 i 个字符为止,字符串中不含有字符 ' h ' 的最少花费,再令dp[ i ][ 2 ]为到第 i 个字符为止,字符串中不含有字序列 “ ha ” 的最少花费,以此类推,一直到dp[ i ][ 4 ],那么以“ har ”的转移为例,我们如果想让第 i 个位置不含有子序列“har”,可以让前 i - 1 个位置中不含有子序列“ha”来转移,或者删掉当前位置的字符' r '来转移,故转移方程为:
dp[ i ][ j ] = min( dp[ i - 1 ][ j - 1 ] ,dp[ i - 1 ][ j ] + cost[ i ] )
答案就是dp[ n ][ 4 ]了
代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cmath>
#include<sstream>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int inf=0x3f3f3f3f;
const int N=1e5+100;
char s[N],str[]=" hard";
LL a[N],dp[N][5];
int main()
{
// freopen("input.txt","r",stdin);
// ios::sync_with_stdio(false);
int n;
scanf("%d%s",&n,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[i][1]=dp[i-1][1]+a[i];
else
dp[i][1]=dp[i-1][1];
}
for(int j=2;j<=4;j++)
for(int i=1;i<=n;i++)
{
if(s[i]==str[j])
dp[i][j]=min(dp[i-1][j-1],dp[i-1][j]+a[i]);
else
dp[i][j]=dp[i-1][j];
}
printf("%lld\n",dp[n][4]);
return 0;
}