1. 程式人生 > >D. Easy Problem dp(有銜接關系的dp(類似於分類討論) )

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

can efi 每一個 構造 cond mat ons 節省空間 push_back

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;
}

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