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