zoukankan      html  css  js  c++  java
  • 括号序列的dp问题模型

    括号序列的dp问题模型

    Codeforces314E

    ◦给定一个长度为n的仅包含左括号和问号的字符串,将问号变成左括号或

    右括号使得该括号序列合法,求方案总数。

    ◦例如(())与()()都是合法的括号序列。

    ◦ n<=3000。

    在括号序列问题中,总是把左括号看作+1,右括号看作-1,要使括号序列合法,只需满足任意一个前缀和大于

    或等于0,且总和为0即可

    设dp[i][j]表示第i个字符,还剩下j个左括号的方案数
    若第i+1个字符是左括号,则dp[i+1][j+1]+=dp[i][j]
    若第i+1个字符是右括号,则dp[i+1][j-1]+=dp[i][j]
    若第i+1个字符是问号,则dp[i+1][j+1]+=dp[i][j],dp[i+1][j-1]+=dp[i][j]
    答案为:dp[n][0]
    

    BZOJ3709

    ◦在一款电脑游戏中,你需要打败n只怪物(从1到n编号)。为了打败第i只

    怪物,你需要消耗d[i]点生命值,但怪物死后会掉落血药,使你恢复a[i]点

    生命值。任何时候你的生命值都不能降到0(或0以下)。

    ◦请问是否存在一种打怪顺序,使得你可以打完这n只怪物而不死掉。

    ◦N<=10^5

    巧妙的贪心题目(之所以引入这道贪心,是因为这道题的解题思路对下一题有帮助)

    引入zhhx的一句话:

    贪心:noip的贪心很多都是按照某种方式排序,然后依次选或处理。

    显然,当a[i]>d[i]时,打第i只怪物会回血,所以先打能回血的怪物

    在能回血的怪物里,我们需要先打d[i]小的怪物,故按照d[i]从小到大排序

    那么对于不能回血的怪物,我们该怎样排序呢?

    首先,如果我们最后能活下来,那么剩余的生命值一定是固定的,所以反着来考虑,和正着是一样的

    反着来想我们需要先打a[i]小的怪物,正着来想就是按照a[i]从大到小排序

    因此我们把这些怪物分成两组,a[i]-d[i]>0的为一组,a[i]-d[i]<0的为一组

    再分别按照d[i]从小到大,a[i]从大到小进行排序

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define Maxn 100100
    #define ll long long
    int n;
    ll z;
    struct node{
         int dec,inc,num;
    }a[Maxn],b[Maxn];
    bool cmp1(node x,node y)
    {
        return x.dec<y.dec;
    }
    bool cmp2(node x,node y)
    {
        return x.inc>y.inc;
    }
    int ans[Maxn];
    int tot1=0,tot2=0;
    int main()
    {
        scanf("%d%lld",&n,&z);
        for(int i=1;i<=n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if(y-x>=0)//
            {
                a[++tot1].dec=x;a[tot1].inc=y;a[tot1].num=i;
            }
            else
            {
                b[++tot2].dec=x;b[tot2].inc=y;b[tot2].num=i;
            }
        }
        sort(a+1,a+tot1+1,cmp1);
        sort(b+1,b+tot2+1,cmp2);
        for(int i=1;i<=tot1;i++)
        {
            z-=a[i].dec;
            if(z<=0){printf("NIE");return 0;}
            z+=a[i].inc;
        }
        for(int i=1;i<=tot2;i++)
        {
            z-=b[i].dec;
            if(z<=0){printf("NIE");return 0;}
            z+=b[i].inc;
        }
        printf("TAK
    ");
        for(int i=1;i<=tot1;i++)printf("%d ",a[i].num);
        for(int i=1;i<=tot2;i++)printf("%d ",b[i].num);
        return 0;
    }
    
  • 相关阅读:
    世界上最受欢迎的色彩出炉了,她的名字叫马尔斯绿
    一步一步学会preload和prefetch
    chrome插件编写中需要了解的几个概念和一些方法
    SVG矢量绘图 path路径详解(贝塞尔曲线及平滑)
    为什么Object.prototype在Function的原型链上与Function.prototype在Object的原型链上都为true
    排序算法总结
    iterm2 "agnoster"主题设置中的一些踩坑 2018.8
    webpack4与babel配合使es6代码可运行于低版本浏览器
    认识JWT
    「前端进阶」彻底弄懂前端路由
  • 原文地址:https://www.cnblogs.com/Akaina/p/11241371.html
Copyright © 2011-2022 走看看