Codeforce 1096:D. Easy Problem(DP,思维)

题目链接:https://codeforc.es/contest/1096/problem/D
题目大意:有一个字符串数组,每个位置有一个权值,删掉这个字符要付出这个位置的字符的权值的代价,字符串中可能包含了 “hard” 字符序列,你要删掉一些字符使得字符串中不会出现 “hard” 子序列,求最小删除代价。

题解:考虑 “hard” 字符串,当前字符是 “d” 时,要么删掉这个 “d”,要么在 "har"里删使得 形成不了 “har”,“使得形成不了har” 和 形成不了 “hard” 是同一性质的子问题,因此可以 dp。

令 t = “hard”,s 为原串。 设状态为dp[i][j],0≤j<4 表示前 i 个字符,删掉一些字符使得不能形成:(“h”,当j = 0;“ha”,当 j = 1;“har”,当 j = 2;“hard”,当 j = 3)。

转移方程:当 s[i] == t[j] 时:
dp[i][j]=min(dp[i−1][j−1],dp[i−1][j]+a[i]) 
否则:
dp[i][j]=dp[i−1][j] 
枚举i,j转移即可

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
typedef long long ll;
int n;
char s[maxn];
char t[5] = "hard";
ll a[maxn];
ll dp[maxn][5];
int main() {
	scanf("%d",&n);
	scanf("%s",s + 1);
	for(int i = 1; i <= n; i++)
		scanf("%lld",&a[i]);
	memset(dp,0,sizeof dp);
	for(int i = 1; i <= n; i++) {
		for(int j = 0; j < 4; j++) {
			dp[i][j] = dp[i - 1][j];
			if(j == 0) {
				if(s[i] == t[j]) 
					dp[i][j] += a[i];
			}
			else {
				if(s[i] == t[j])
					dp[i][j] = min(dp[i - 1][j - 1],dp[i][j] + a[i]);
			}
		}
	}
	printf("%lld\n",dp[n][3]);
	return 0;
}

 

posted @ 2019-09-10 17:22  Shmilky  阅读(48)  评论(0编辑  收藏  举报