CodeForces - 1096D Easy Problem(线性dp)

题目链接:点击查看

题目大意:给出一个字符串,每个字符都有一个权值,现在需要删除权值和最少的字符,满足字符串中不再含有子序列“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;
}
发布了558 篇原创文章 · 获赞 16 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/104078797