Fork me on GitHub

Codeforces 1096D-Easy Problem

Codeforces 1096D-Easy Problem

题意

给一个长度为n的字符串s,以及数组a,a[i]表示删除s[i]所需要的花费。问要让字符串s中不包含“hard”的子序列所需要的最小花费。

题解

dp[i][0]表示前i个字符中不包含'h'的最小花费,dp[i][1]表示前i个字符中不包含'ha'的最小花费...
那么如果当前字符为'h',可以得到递推式dp[i][0]=dp[i-1][0]+a[i],dp[i][1]=min(dp[i-1][0],dp[i-1][1]),如果当前字符为'a',可以得到dp[i][1]=dp[i-1][1]+a[i],dp[i][2]=min(dp[i-1][1],dp[i-1][2])...
考虑到二维数组只用到了两层,所以可以压缩到一层,变成一维dp。

代码1

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N=1e5+10;
ll a[N],dp[N][5];
int n;
char s[N];


int main(){
	scanf("%d",&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[i][0]=dp[i-1][0]+a[i];
			dp[i][1]=min(dp[i-1][0],dp[i-1][1]);
			dp[i][2]=dp[i-1][2];
			dp[i][3]=dp[i-1][3];
		}else if(s[i]=='a'){
			dp[i][0]=dp[i-1][0];
			dp[i][1]=dp[i-1][1]+a[i];
			dp[i][2]=min(dp[i-1][1],dp[i-1][2]);
			dp[i][3]=dp[i-1][3];
		}else if(s[i]=='r'){
			dp[i][0]=dp[i-1][0];
			dp[i][1]=dp[i-1][1];
			dp[i][2]=dp[i-1][2]+a[i];
			dp[i][3]=min(dp[i-1][2],dp[i-1][3]);
		}else if(s[i]=='d'){
			dp[i][0]=dp[i-1][0];
			dp[i][1]=dp[i-1][1];
			dp[i][2]=dp[i-1][2];
			dp[i][3]=dp[i-1][3]+a[i];
		}else{
			for(int j=0;j<=3;j++) dp[i][j]=dp[i-1][j];
		}
	}
	ll ans=min(dp[n][0],min(dp[n][1],min(dp[n][2],dp[n][3])));
	printf("%lld\n",ans);
	return 0;
}

代码2

更简洁的写法

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N=1e5+10;
ll a[N],dp[N][5];
int n;
char s[N],str[]="*hard";


int main(){
	scanf("%d",&n);
	scanf("%s",s+1);
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
	memset(dp, 0x3f, sizeof dp);
	for(int i = 1; i <= 4; i++) dp[0][i] = 0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=4;j++){
			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];
		}
	}
	ll ans=min(dp[n][1],min(dp[n][2],min(dp[n][3],dp[n][4])));
	printf("%lld\n",ans);
	return 0;
}

代码3(一维)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=1e5+10;
ll a[N],dp[5];
char s[N];
int n;

int main(){
	scanf("%d",&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[0]+=a[i];
		}else if(s[i]=='a'){
			dp[1]=min(dp[0],dp[1]+a[i]);
		}else if(s[i]=='r'){
			dp[2]=min(dp[1],dp[2]+a[i]);
		}else if(s[i]=='d'){
			dp[3]=min(dp[2],dp[3]+a[i]);
		}
	}
	ll ans=dp[3];
	printf("%lld\n",ans);
	return 0;
}
posted @ 2020-03-19 14:10  qjy_73  阅读(168)  评论(0)    收藏  举报