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;
}