HDU 4315 Save the dwarfs 动态规划

题目描述:

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.

题目分析:

题目的大意是有一个n个人被困在一个深度为h坑中,n个人有其不同的身高和手臂长度,他们可以站在别人的肩膀上,最上面的人可以通过用手臂离开深坑。求最多能够使多少人离开深坑?
动态规划题 具体看代码吧

代码如下:

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>

using namespace std;
const int MAXN=2005;
const int INF=0x3f3f3f3f;

struct sa
{
    int a,b;
    int tot;
} dwarf[MAXN];

bool cmp (const sa &a,const sa &b)
{
    return a.tot>b.tot;
}

int dp[MAXN][MAXN];//dp[i][j]表示总共i个人中逃脱j个所需要的最小高度
int pyramid[MAXN];
int n,h;

void DP()
{
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=i; j++)
        {
            dp[i][j]=min(dp[i-1][j]-dwarf[i-1].a, max(dp[i-1][j-1], h-pyramid[i-1]-dwarf[i-1].b));
        }//情况1:第i个人没逃脱
        //情况2:第i个人通过矮人金字塔逃脱了
        //情况3:第i个人通过矮人金字塔和自己手臂逃脱了
    }
    for(int i=n; i>=0; i--)
    {
        if(dp[n][i]<=0)
        {
            printf("%d\n",i);//若dp[n][i]<=0 说明能够逃脱i个人 从大到小遍历就能得出最多可能逃脱的人数
            break;
        }
    }
}


int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=0; i<n; i++)
        {
            scanf("%d%d",&dwarf[i].a,&dwarf[i].b);
            dwarf[i].tot=dwarf[i].a+dwarf[i].b;
        }
        scanf("%d",&h);
        sort(dwarf,dwarf+n,cmp);//将矮人的总身高从大到小排序 相当于底层的是总身高高的矮人
        pyramid[0]=dwarf[0].a;
        for(int i=1; i<n; i++)
        {
            pyramid[i]=pyramid[i-1]+dwarf[i].a;//将矮人叠成金字塔
        }
        memset(dp,0,sizeof(dp));
        for(int i=0; i<=n; i++)
        {
            for(int j=i+1; j<=n; j++)
                dp[i][j]=INF;//排除不可能情况
        }
        DP();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值