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],0j<40 \leq j < 4, 表示前 i 個字符,刪掉一些字符使得不能形成:(“h”,當j = 0;“ha”,當 j = 1;“har”,當 j = 2;“hard”,當 j = 3)。

轉移方程:當 s[i] == t[j] 時:dp[i][j]=min(dp[i1][j1],dp[i1][j]+a[i])dp[i][j] = min(dp[i - 1][j - 1],dp[i - 1][j] + a[i])否則:dp[i][j]=dp[i1][j]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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章