/*
分析:
dp。
“一个重要的观察是,如果某些矮人可以逃脱,那么我们总可以把他们的
逃脱顺序按照Ai+Bi递增排序(即Ai+Bi最小的先逃脱),得到的结果不会更
坏。”,这个发现我是没有发现囧~,不过证明了一下:
有n个人,设每个人的高度为hi、手长li、总长ti,现在这n个人中有a、b
以及其他人,a、b是ti最小的俩,且tb>=ta,设其他人的总身高为base,那么:
如果a站在base上面可以出去,那么b站在base上面也可以出去;
而如果b站在b上面可以出去,那么a站在base上面不一定可以出去;
所以让a站在base+b上面,试试能不能让a先出去,总归不是一个更坏
的决策;
把这个关系推到全局,那么没有比“尽量让ti最小的先出去”更好的决策。
dp[i][j]表示最后i个人能逃出j个时,需要之前井中剩下的人的最小A高
度之和。则转移方程:
dp[i][j] = min(dp[i-1][j] - s[i-1].a, max(dp[i-1][j-1], H - sumA[i-1] - s[i-1].b )),
满足dp[i][j]<=0的最大的j既为所求。
2013-04-22
*/
分析:
dp。
“一个重要的观察是,如果某些矮人可以逃脱,那么我们总可以把他们的
逃脱顺序按照Ai+Bi递增排序(即Ai+Bi最小的先逃脱),得到的结果不会更
坏。”,这个发现我是没有发现囧~,不过证明了一下:
有n个人,设每个人的高度为hi、手长li、总长ti,现在这n个人中有a、b
以及其他人,a、b是ti最小的俩,且tb>=ta,设其他人的总身高为base,那么:
如果a站在base上面可以出去,那么b站在base上面也可以出去;
而如果b站在b上面可以出去,那么a站在base上面不一定可以出去;
所以让a站在base+b上面,试试能不能让a先出去,总归不是一个更坏
的决策;
把这个关系推到全局,那么没有比“尽量让ti最小的先出去”更好的决策。
dp[i][j]表示最后i个人能逃出j个时,需要之前井中剩下的人的最小A高
度之和。则转移方程:
dp[i][j] = min(dp[i-1][j] - s[i-1].a, max(dp[i-1][j-1], H - sumA[i-1] - s[i-1].b )),
满足dp[i][j]<=0的最大的j既为所求。
2013-04-22
*/
#include"iostream"
#include"cstdio"
#include"cstring"
#include"algorithm"
using namespace std;
const int N=2012;
int n,limit;
int sum[2012],dp[2][2012];
struct node{
int h,l;
}E[N];
int min(int a,int b){
return a>b?b:a;
}
int max(int a,int b){
return a>b?a:b;
}
int cmp(node n1,node n2){
return n1.h+n1.l>n2.h+n2.l;
}
int solve()
{
int i,l;
int pre,now,t=1<<30;
int ans=0;
dp[0][0]=0;
for(l=1;l<=n;l++) dp[0][l]=t;
for(i=1;i<=n;i++)
{
now=i%2;
pre=1-now;
for(l=0;l<=i;l++) dp[now][l]=0;
for(;l<=n;l++) dp[now][l]=t;
for(l=1;l<=i;l++)
{
dp[now][l]=min(dp[pre][l]-E[i].h,max(dp[pre][l-1],limit-sum[i]-E[i].l));
if(dp[now][l]<=0 && ans<l) ans=l;
}
}
return ans;
}
int main()
{
int i;
while(scanf("%d",&n)!=-1)
{
for(i=1;i<=n;i++) scanf("%d%d",&E[i].h,&E[i].l);
scanf("%d",&limit);
E[0].h=E[0].l=0;
sum[0]=0;
sort(E+1,E+n+1,cmp);
for(i=1;i<=n;i++) sum[i]=sum[i-1]+E[i].h;
printf("%d\n",solve());
}
return 0;
}