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;
    }
    
  • 相关阅读:
    jquery tmpl 模板引擎 取小数点 三目运算
    ztree 根据id选中某一点且触发当前点的click事件
    rgb(123,25,62)拆分
    html5 vedio
    同一个dom上加单击事件和双击事件的冲突解决办法,双击事件方法进不去
    axios拦截器
    foreach、for、for in循环方式
    echarts markline 不同颜色
    组件里传值到父级
    vue路由钩子拦截器beforeEach和afterEach及页面路由变化路由监听
  • 原文地址:https://www.cnblogs.com/Akaina/p/11241371.html
Copyright © 2011-2022 走看看