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

Source

难点在排序上,$dp$很好想,设$f[i][j]$前$i$个人表示走了$j$个的最大剩余高度,枚举当前矮人是否逃离即可。排序是按照身高+臂长排序的,这里我说一下我的理解:如果都出不去或都能出去就没必要再讨论了。我们应该选择逃生能力强的放在后边,然后$dp$枚举每个人选还是不选。

代码:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define M 2010
using namespace std;
struct point{int x,y;}a[M];
int n,ans,h;
int f[M][M];//前i个走了j个后最大高度
bool cmp(point a1,point a2) {return a1.x+a1.y<a2.x+a2.y;}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
sort(a+,a++n,cmp);
memset(f,,sizeof(f));
f[][]=;
for(int i=;i<=n;i++) f[][]+=a[i].x;
scanf("%d",&h);
for(int i=;i<=n;i++)
for(int j=;j<=i;j++)
{
f[i][j]=f[i-][j];
if(!j) continue;
if(f[i-][j-]+a[i].y>=h) f[i][j]=max(f[i][j],f[i-][j-]-a[i].x);
}
for(int i=;i<=n;i++) if(f[n][i]>=) ans=i;
printf("%d",ans);
return ;
}
05-18 03:02