Codeforces 1096D Easy Problem 【DP】

<题目链接>

题目大意:

给你一个字符串,每个字符有权值,问现在删除字符串中的字符使其中没有"hard"的最小代价是多少。

解题分析:

用DP来求解:        转载于 >>>

dp[i][1]:表示字符串s的前i个字符中不含有前缀'h'的最小代价

dp[i][2]:表示字符串s的前i个字符中不含有前缀'ha'的最小代价

dp[i][3]:表示字符串s的前i个字符中不含有前缀'har'的最小代价

dp[i][4]:表示字符串s的前i个字符中不含有前缀'hard'的最小代价

对于状态转移,例如对dp[i][3],如果位置i的字符不是r,那么dp[i][3] = dp[i - 1][3];
否则,要么去掉位置i的字符,则代价为dp[i - 1][3] + a[i],如果不去除该位置字符,那么之前的序列不能含有'ha',则代价为dp[i - 1][2]。

#include <bits/stdc++.h>
using namespace std;

#define N int(1e5+7)
typedef long long ll;
ll dp[N][5],arr[N];
char s[N];
const ll INF = 1e18;
const char str[]="0hard";

int main(){
    int n;scanf("%d",&n);
    scanf("%s",s+1);
    for(int i=1;i<=n;i++)scanf("%d",&arr[i]);
    for(int i=1;i<=n;i++)dp[i][0]=INF;
    if(s[1]=='h')dp[1][1]=arr[1];
    for(int i=2;i<=n;i++)
        for(int j=1;j<=4;j++){
            if(s[i]!=str[j])dp[i][j]=dp[i-1][j];  
            else dp[i][j]=min(dp[i-1][j]+arr[i],dp[i-1][j-1]); //以j=3为例,dp[i-1][j]为前i-1项不含'har',并且去除第j项的'r'的代价(因为前i-1项可能包含'ha'),dp[i-1][j-1]表示前i-1项连'ha'都不包含
        }
    printf("%lld\n",dp[n][4]);
}

一维的写法:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
ll dp[5];
char s[int(1e5+7)];
const char ss[]="0hard";
int main(){
    int n;cin>>n;
    scanf("%s",s+1);
    for(int i=1;i<=n;i++){
        ll now;scanf("%lld",&now);
        if(s[i]=='h')dp[1]+=now;
        for(int j=2;j<=4;j++)
            if(s[i]==ss[j])dp[j]=min(dp[j]+now,dp[j-1]);
    }
    printf("%lld\n",dp[4]);
}

2019-02-17

猜你喜欢

转载自www.cnblogs.com/00isok/p/10392252.html