D. Easy Problem dp(有銜接關系的dp(類似於分類討論) )


D. Easy Problem dp(有銜接關系的dp(類似於分類討論) )

題意

給出一個串 給出刪除每一個字符的代價問使得串里面沒有hard的子序列需要付出的最小代價(子序列不連續也行)

思路

要滿足hard 先要滿足har 要滿足har 先要滿足ha 一次類推
這類問題的一個共同點是要每個地方都要滿足一系列前置條件才能成立也就是說有銜接關系
所以如果是構造問題 那么dp數組加一維已經滿足了幾個,如果是刪除問題dp數組加一維 切斷了哪一個即可
所以我們可以設置dp數學 dp[i][1,2,3,4] 表示在i位置時 字符是h,a,r,d 對應於 1,2,3,4使得以h,a,r,d為前綴不存在的所需要消耗的最小代價是多少

這樣\(dp[i][1]=dp[i-1][1]+a[i]\) 表示要使得h不存在 有h就要刪掉h
\(dp[i][2]=max(dp[i-1][1],dp[i-1][2]+a[i])\)要使得ha不存在 要么沒有h 要么沒有a
\(dp[i][3]=max(dp[i-1][2],dp[i-1][3]+a[i])\)要使得har成立 要么沒有要么a 要么沒有r
\(dp[i][4]=max(dp[[i-1][3],dp[i-1][4]+a[i])\)同上
注意 這里i可以用滾動數組滾掉節省空間 不然開不下 記得開long long

#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5+5;
#define int long long 
#define F first
#define S second
#define pb push_back
#define pii pair<int ,int >
#define mkp make_pair
const int inf=0x3f3f3f3f;
char s[maxn];
int a[maxn];
int dp[10];
int32_t main(){
	int n;
	scanf("%lld",&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[1]=dp[1]+a[i];
		if(s[i]=='a')dp[2]=min(dp[1],dp[2]+a[i]);
		if(s[i]=='r')dp[3]=min(dp[2],dp[3]+a[i]);
		if(s[i]=='d')dp[4]=min(dp[3],dp[4]+a[i]);
	}
	cout<<dp[4]<<endl;
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM