zoukankan      html  css  js  c++  java
  • CF1096D Easy Problem(DP)

    貌似最近刷了好多的CF题……

    题目链接:CF原网  洛谷

    题目大意:有一个长度为 $n$ 的字符串 $s$,删除第 $i$ 个字符需要代价 $a_i$。问使得 $s$ 不含有子序列(不是子串)"hard" 的最小花费。

    $1le nle 10^5,1le a_ile 10^9$,$s$ 只包含小写字母。


    其实就是一简单DP。

    $dp[i][j]$ 表示考虑到 $s$ 的前缀 $i$,目前最远能匹配到 "hard" 的位置,的最小花费。

    比如,$dp[3][2]$ 表示考虑 $s$ 的前三个字符,目前最远能匹配到 "ha" 的最小花费。

    初始状态 $dp[0][j]=0$。

    转移:如果 $s[i] eq hard[j+1]$,说明如果删不删 $i$ 都不会使 $j$ 变大,那么 $dp[i][j]=min(dp[i-1][j])$。

    否则,如果选择删掉 $i$,$dp[i][j]=min(dp[i-1][j]+a[i])$。

    否则,就是不删掉 $i$。$dp[i][j]=min(dp[i-1][j-1])$。注意判断边界 $j=0$。

    答案就是 $dp[n][0/1/2/3]$ 的最大值。不能匹配到第四位。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=100010;
    const char hard[6]="*hard";    //hard[0]表示什么都没有,hard[i]表示第i个字符
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    inline int read(){
        char ch=getchar();int x=0,f=0;
        while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return f?-x:x;
    }
    int n,a[maxn];
    char str[maxn];
    ll dp[maxn][4];
    int main(){
        n=read();
        scanf("%s",str+1);
        FOR(i,1,n) a[i]=read();
        MEM(dp,0x3f);
        FOR(j,0,3) dp[0][j]=0;
        FOR(i,1,n) FOR(j,0,3){
            if(str[i]!=hard[j+1]) dp[i][j]=min(dp[i][j],dp[i-1][j]);    //不会匹配更远,不删
            else{
                dp[i][j]=min(dp[i][j],dp[i-1][j]+a[i]);    //删掉
                if(j) dp[i][j]=min(dp[i][j],dp[i-1][j-1]);    //不删
            }
        }
        ll ans=LLONG_MAX;
        FOR(j,0,3) ans=min(ans,dp[n][j]);    //取最小值
        printf("%lld
    ",ans);
    }
    View Code
  • 相关阅读:
    迭代器基础知识
    C语言I博客作业09
    第一周作业
    C语言1博客作业04
    C语言I博客作业08
    C语言博客作业05
    C语言I作业12—学期总结
    C语言I博客作业10
    C语言I博客作业06
    C语言I博客作业11
  • 原文地址:https://www.cnblogs.com/1000Suns/p/10361376.html
Copyright © 2011-2022 走看看