题目链接:http://codeforces.com/problemset/problem/1096/D
题意:
现在有一个由小写字母组成的字符串,去掉这个字符串的第i个位置会有a[i]的代价,问去掉一些字符使得该字符串中不包含一个子序列为hard的最小代价和。
思路:
这题一看就是一个 dp 的问题,和背包问题有点像。
首先我们定义下 dp[i][1] 代表 匹配到 i 的时候 不存在 前缀 'h' 的最小代价
之后的以此类推
那么就来到了删和不删的问题了。具体的还是看代码吧
1 #include <iostream> 2 #include <algorithm> 3 #include <stdlib.h> 4 #include <cstring> 5 #include <string> 6 #include <string.h> 7 #include <set> 8 #include <queue> 9 #include <stdbool.h> 10 11 #define LL long long 12 using namespace std; 13 const int maxn = 1e5 + 10; 14 LL inf = 1e15; 15 16 LL arr[maxn]; 17 char s[maxn]; 18 char ss[5] = {'p','h','a','r','d'}; 19 LL dp[maxn][5]; 20 21 int main(){ 22 int n; 23 scanf("%d",&n); 24 scanf("%s",s+1); 25 for (int i=1;i<=n;i++){ 26 scanf("%lld",&arr[i]); 27 dp[i][0] = inf; 28 } 29 if (s[1] == 'h') 30 dp[1][1] = arr[1]; 31 for (int i=2;i<=n;i++){ 32 for (int j=1;j<=4;j++){ 33 if (s[i] == ss[j]){ // 出现了一个,我们可以考虑删和不删这个字母。 如果不删这个字母,那么就不能有它前面的。例如 出现了'r' ,那么我们就不能让它之前出现 'h' 'a' 34 dp[i][j] = min(dp[i-1][j-1],dp[i-1][j]+arr[i]); // 如果删这个字母,那就直接加上代价就好了 35 } 36 else{ 37 dp[i][j] = dp[i-1][j]; // 如果没有出现,我们就让后面的等于前面出现了的。方便后面我们的输出 38 } 39 } 40 } 41 printf("%lld ",dp[n][4]); 42 return 0; 43 }