BZOJ_3174_[Tjoi2013]拯救小矮人_貪心+DP
阿新 • • 發佈:2018-03-30
script 希望 深度 sca rip pan main mem 是我
2
20 10
5 5
30
樣例2
2
20 10
5 5
35
2
樣例2
1
BZOJ_3174_[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
樣例12
20 10
5 5
30
樣例2
2
20 10
5 5
35
Sample Output
樣例12
樣例2
1
HINT
數據範圍
30%的數據 N<=200
100%的數據 N<=2000
分析:
這道題其實是在求一個子序列。在某種方案下都能夠逃跑的子序列中最長的一個。
我們先貪心地確定逃跑方案。
首先,對於兩個一定要逃跑的人x和y,如果a[x]+a[y]<b[x]+b[y],說明x比y弱,不妨讓x先逃跑。
於是我們可以按a+b排一下序。
然後找最長的子序列。設f[i][j]為前i個人,走了j個後最高的高度。
f[i][j]=f[i-1][j]; f[i][j]=max(f[i][j],f[i-1][j-1]-a[j])(b[j]+f[i-1][j-1]>=h)
代碼:
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define N 2050 struct A { int a,b; }a[N]; int h,n,f[N][N]; bool cmp(const A &x,const A &y) { return x.a+x.b<y.a+y.b; } int main() { scanf("%d",&n); int i, ans=0, j; memset(f,-1,sizeof(f)); f[0][0]=0; for(i=1;i<=n;++i) scanf("%d%d",&a[i].a,&a[i].b),f[0][0]+=a[i].a; sort(a+1,a+n+1,cmp); scanf("%d",&h); for(i=0;i<n;++i) { f[i+1][0]=f[i][0]; for(j=0;j<=ans;j++) { f[i+1][j+1]=f[i][j+1]; if(f[i][j]+a[i+1].b>=h) { f[i+1][j+1]=max(f[i+1][j+1],f[i][j]-a[i+1].a); } } if(f[i+1][ans+1]>=0) ans++; } printf("%d\n",ans); }
BZOJ_3174_[Tjoi2013]拯救小矮人_貪心+DP