hdu 4314 Save the dwarfs(dp,4级,多校)

Save the dwarfs

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 926    Accepted Submission(s): 281


Problem Description
Several dwarfs are trapped in a deep well. They are not tall enough to climb out of the well, so they want to make a human-pyramid, that is, one dwarf stands on another's shoulder, until the dwarf on the top can reach the top of the well when he raise his arms up. More precisely speaking, we know the i-th dwarf's height from feet to shoulder is Ai, and his arm length Bi. And we know the height of the well is H. If we can build a dwarf-tower consists of dwarf 1, dwarf 2, ..., dwarf k from bottom to top, such that A1 + A2 + ... + Ak-1 + Ak + Bk >= H, then dwarf k can escape from the well. Obviously, the escaped dwarf can't be used to build tower again.

We want the escaped dwarfs as many as possible. Please write a program to help the dwarfs.
 

Input
The first line of each test case contains N, (1 <= N <= 2000) the number of trapped dwarfs. Each of the following N lines contains two integers Ai and Bi. The last line is H, the height of the well. All the integers are less than 100,000.
 

Output
Output one line for each test case, indicating the number of dwarfs escaped at most.
 

Sample Input
2 20 10 5 5 30 2 20 10 5 5 35
 

Sample Output
2 1
Hint
For the first case, the tall dwarf can help the other dwarf escape at first. For the second case, only the tall dwarf can escape.
 

Author
TJU
 

Source
 

Recommend
zhuyuanchen520


dp[i][j]代表由大到小排序后,前i人中能逃脱j人需要之前的人留在井中的高度和。

每一次必然是身高和臂长和短的人先逃出去,dp[i][j]只可能由两种情况得来:

dp[i-1][j]:代表i位置的人没出去,所以所需的高度就是dp[i-1][j] - a[i]。

dp[i-1][j-1]:代表i位置的人出去了,所需高度有两种情况:

1. i的身高和臂长之和足够大,利用之前所需高度就可以逃脱,这是所需高度是dp[i-1][j-1]。

2. i的身高和臂长之和不够大,因为每一次必然是短的人先出去,而排序后i的长度必然最短,所以需要的高度就是后i-1个人帮助i逃脱,所需高度是H - sumA[i] - b[i]。

这两种情况要取最大值。


综上所述,最终的递推公式就是:

dp[i][j] = min(dp[i-1][j] - a[i], max(dp[i-1][j-1], H - sumA[i] - b[i]);

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int mm=2e3+9;
class node
{
public:
    int a,b;
    bool operator<(const node&x)const
    {
        return a+b>x.a+x.b;
    }
} f[mm];
int dp[mm][mm],n,suma[mm];
int main()
{
    int hh;
    while(~scanf("%d",&n))
    {
        suma[0]=0;
        for(int i=1; i<=n; ++i)
        {
            scanf("%d%d",&f[i].a,&f[i].b);
        }
        scanf("%d",&hh);
        sort(f+1,f+n+1);
        for(int i=1; i<=n; ++i)
        {
            suma[i]=suma[i-1]+f[i].a;
        }
        ///memset(dp,0,sizeof(dp));
        dp[0][0]=0;
        for(int i=0; i<=n; ++i)
            for(int j=i+1; j<=n; ++j)
                dp[i][j]=1e9;
        for(int i=1; i<=n; ++i) ///前i个人出j个需要留下的最小长度
            for(int j=0; j<=i; ++j)
            {
                dp[i][j]=dp[i-1][j]-f[i].a;
                if(j)
                    dp[i][j]=min(dp[i][j],max(dp[i-1][j-1],hh-suma[i]-f[i].b));
            }
        /// for(int i=0;i<=n;++i)
        //cout<<" "<<dp[n][i]<<" ";puts("");
        for(int i=n; i>=0; --i)
            if(dp[n][i]<=0)
            {
                printf("%d\n",i);
                break;
            }
    }
    return 0;
}







posted @ 2013-06-01 10:16  剑不飞  阅读(212)  评论(0编辑  收藏  举报