BZOJ3174:[TJOI2013]拯救小矮人(DP)
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
2
20 10
5 5
30
样例2
2
20 10
5 5
35
Sample Output
样例1
2
样例2
1
2
样例2
1
HINT
数据范围
30%的数据 N<=200
100%的数据 N<=2000
Solution
证明戳这里吧
$f[i]$表示跑了$i$个人后剩下的能组成的人梯的最高高度
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #define N (2009) 6 using namespace std; 7 8 struct Node 9 { 10 int x,y; 11 bool operator < (const Node &a) const 12 { 13 return x+y<a.x+a.y; 14 } 15 }a[N]; 16 int n,h,f[N],ans,sum; 17 18 int main() 19 { 20 scanf("%d",&n); 21 for (int i=1; i<=n; ++i) 22 scanf("%d%d",&a[i].x,&a[i].y),sum+=a[i].x; 23 scanf("%d",&h); 24 sort(a+1,a+n+1); 25 memset(f,-1,sizeof(f)); 26 f[0]=sum; 27 for (int i=1; i<=n; ++i) 28 for (int j=ans; j>=0; --j) 29 { 30 if (f[j]+a[i].y>=h) 31 f[j+1]=max(f[j+1],f[j]-a[i].x); 32 if (f[ans+1]>=0) ans++; 33 } 34 printf("%d\n",ans); 35 }