http://acm.hdu.edu.cn/showproblem.php?pid=4314
dp,dp[i][j]表示i个小矮人能逃出去j个时需要之前井中剩下的人的最小a高度之和
转移方程dp[i][j]=min(dp[i-1][j]-kk[i-1].a,max(dp[i-1][j-1],h-sumA[i-1]-kk[i-1].b))
最神的是解题报告直接把a+b排了个序(a+b最小的先逃脱),这个自己没看出来。。。
View Code
#include <iostream> #include <algorithm> using namespace std ; const int INF=0xfffffff ; int dp[2001][2001] ; int sumA[2001] ; typedef struct L{ int a,b ; int temp ; }L ; L kk[2001] ; bool cmp(L a,L b) { return a.temp>b.temp ; } int main() { int n ; while(~scanf("%d",&n)) { for(int i=0;i<n;i++) { scanf("%d%d",&kk[i].a,&kk[i].b) ; kk[i].temp=kk[i].a+kk[i].b ; } int h ; scanf("%d",&h) ; sort(kk,kk+n,cmp) ; sumA[0]=kk[0].a ; for(int i=1;i<n;i++) sumA[i]=sumA[i-1]+kk[i].a ; for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) dp[i][j]=INF ; dp[0][0]=0 ; for(int i=1;i<=n;i++) for(int j=0;j<=i;j++) { if(j) dp[i][j]=min(dp[i-1][j]-kk[i-1].a,max(dp[i-1][j-1],h-sumA[i-1]-kk[i-1].b)) ; else dp[i][j]=min(dp[i-1][j]-kk[i-1].a,h-sumA[i-1]-kk[i-1].b) ; } int i ; for(i=n;i>=0;i--) if(dp[n][i]<=0) break ; printf("%d\n",i) ; } return 0 ; }