zoukankan      html  css  js  c++  java
  • [luogu]P4823 [TJOI2013]拯救小矮人

    原题链接 :P4823 [TJOI2013]拯救小矮人

    分析

    有n个矮人,每个人有肩膀高和手长,一堆矮人叠在一起的高度为(((sum)肩膀高)+最后一个人的手长)。
    如果这个高度大于陷阱高度,最后一个人可以离开陷阱。
    问最多有多少人可以离开。

    一个直观的想法是按照身高+手长排序。
    大胆猜想,无需证明!
    我们可以想象,身高+手长小的肯定逃跑能力比较弱。
    我们尝试先让逃跑能力弱的逃跑,如果逃不出去,那么我们就把他垫在底下,让下面的人逃跑。
    然后我们可以跑一个dp。
    (f[i])表示逃走i个人之后的最大高度,(p[i].a,p[i].b)表示第i个人的身高和手长,h表示陷阱高度。
    我们从小到大让每一个人逃跑,那么

    [f[j+1]=max{f[j]-p[i].a,f[j]+p[i].bge h} ]

    在循环的时候顺便更新j的最大值。
    注意要倒序循环,因为第i个人逃跑之后会更新j+1的最大值,按照01背包的思想,我们倒序循环才能保证程序正确。

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #define ll long long
    using namespace std;
    struct P{
        int a,b;
    }p[2009];
    int read(){
        char c;int num,f=1;
        while(c=getchar(),!isdigit(c))if(c=='-')f=-1;num=c-'0';
        while(c=getchar(), isdigit(c))num=num*10+c-'0';
        return f*num;
    }
    int n,f[2009],res=0,h;
    bool cmp(P a,P b){return a.a+a.b<b.a+b.b;}
    int main()
    {
        memset(f,-1,sizeof(f));
        n=read();f[0]=0;
        for(int i=1;i<=n;i++){
            p[i].a=read();
            p[i].b=read();
            f[0]+=p[i].a;
        }
        h=read();
        sort(p+1,p+1+n,cmp);
        for(int i=1;i<=n;i++){
            for(int j=res;j>=0;j--){
                if(f[j]+p[i].b>=h)
                    f[j+1]=max(f[j+1],f[j]-p[i].a);
                if(f[res+1]>=0)res++;
            }
        }
        printf("%d
    ",res);
        return 0;
    }
    
  • 相关阅读:
    数据持久化-- json、pickle
    socket编程介绍
    RHEL/CentOS 下安装yum源地址汇集---不定期更新
    设置阿里云pip源,加速pip更新速度
    pacemaker+corosync+haporxy高可用集群部署
    etcd数据库备份与还原
    PEM格式的证书转换格式
    CentOS 7 上 yum 安装python3
    webconsole提示undefined: ssh.InsecureIgnoreHostkey错误解决方案
    oh my zsh 配置文件
  • 原文地址:https://www.cnblogs.com/onglublog/p/9880863.html
Copyright © 2011-2022 走看看