bzoj3174 [Tjoi2013]拯救小矮人

http://www.elijahqi.win/archives/3117
Description

一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯。即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以碰到陷阱口。对于每一个小矮人,我们知道他从脚到肩膀的高度Ai,并且他的胳膊长度为Bi。陷阱深度为H。如果我 们利用矮人1,矮人2,矮人3,。。。矮人k搭一个梯子,满足A1+A2+A3+….+Ak+Bk>=H,那么矮人k就可以离开陷阱逃跑了,一 旦一个矮人逃跑了,他就不能再搭人梯了。
我们希望尽可能多的小矮人逃跑, 问最多可以使多少个小矮人逃跑。

Input

第一行一个整数N, 表示矮人的个数,接下来N行每一行两个整数Ai和Bi,最后一行是H。(Ai,Bi,H<=10^5)
Output

一个整数表示对多可以逃跑多少小矮人
Sample Input

样例1

2
20 10
5 5
30

样例2
2
20 10
5 5
35

Sample Output

样例1
2
样例2
1

HINT

数据范围

30%的数据 N<=200

100%的数据 N<=2000

首先如果在所有东西都确定好的情况下 考虑最上方的两个矮人 如果都能出去交换 不影响 都不能出去 交换 不影响 有影响的仅仅在于交换之后可能一个出不去了 那这种情况下 一定是臂展加身高最长的放在下面会更好 但是并不是所有情况都是这样好 但是可以确定的是在满足条件下这样一定最好所以先这样排序 然后去dp即可 设dp[i]表示走了i个矮人的最高距离 不能枚举走了几个 而是应该枚举这一轮是谁走的避免算重

#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
inline char gc(){
    static char now[1<<16],*S,*T;
    if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S)return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}
    while(isdigit(ch)) x=x*10+ch-'0',ch=gc();
    return x*f;
}
const int N=2020;
struct node{
    int a,b;
}p[N];
inline bool cmp(const node &a,const node &b){return a.a+a.b<b.a+b.b;}
int n,ans,dp[N],H;
int main(){
    freopen("bzoj3174.in","r",stdin);
    n=read();
    for (int i=1;i<=n;++i) p[i].a=read(),p[i].b=read(),dp[0]+=p[i].a;
    sort(p+1,p+n+1,cmp);H=read();//dp[i]-> i people has been away from
    for (int i=1;i<=n;++i){
        for(int j=ans;~j;--j){
            if (dp[j]+p[i].b>=H) {
                ans=max(ans,j+1);
                dp[j+1]=max(dp[j+1],dp[j]-p[i].a);
            }if (dp[j+1]) ans=max(ans,j+1);
        }
    }printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值