• 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;
    }
    
  • 相关阅读:
    poj2388-Who's in the Middle(排序)
    poj1543-Perfect Cubes(暴力)
    poj1664-放苹果(递归)
    快速幂
    poj2389-Bull Math(大整数乘法)
    HDU2608-0 or 1(数论+找规律)
    poj1131-Octal Fractions(进制转换)
    [noip2011 d1t2]选择客栈
    [周记]8.7~8.16
    [noip2012d1t2] 国王游戏
  • 原文地址:https://www.cnblogs.com/ttttttttrx/p/10800144.html
Copyright © 2020-2023  润新知