HDU 4314 Save the dwarfs (DP) ---转载

题目:传送门

这个是DP,比赛的时候用贪心写了好久没写出来。

题意:

有n个矮人被困在深度为h的井中,每个矮人都ai(脚到肩膀的高度)和bi(手臂长度), 当存在a1 + a2 + ... + ak-1 + ak+ bk >= h,矮人k可以从井中逃脱出去。问最多能逃出去几个人。

题解:

dp[i][j]代表的是在前i个人中能逃脱出j个人后,剩余井中矮人再想逃脱出至少一人还需要的最小高度是多少,分析如下,逃脱出的j个人中最后逃脱的一定是 ai +bi最大的,这样才能得到dp值是最优的,需要首先对矮人按照ai + bi从大到小排序,考虑当前第i个人可以逃脱可以不逃脱,即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],所以需要取最大值,
综上得dp方程:dp[i][j] = MIN(dp[i-1][j] - dwarf[i].a , MAX(dp[i-1][j-1] , h - sum[i] -dwarf[i].b));

#include <iostream>
#include <cstdio>
#include <memory.h>
#include <algorithm>
#define MIN(a , b) ((a) < (b) ? (a) : (b))
#define MAX(a , b) ((a) > (b) ? (a) : (b))
using namespace std;
const int inf = 1 << 29;
const int maxn = 2002;
struct D
{
    int a,b;
    bool operator < (const D &other) const
    {
        return a + b > other.a + other.b;
    }
}dwarf[maxn];
int sum[maxn],dp[maxn][maxn];
int n,h;

void read()
{
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=n;i++)
    {
        scanf("%d %d",&dwarf[i].a,&dwarf[i].b);
    }
    scanf("%d",&h);
    sort(dwarf + 1 , dwarf + n + 1);
    sum[0] = 0;
    for(int i=1;i<=n;i++)
    {
        sum[i] = sum[i-1] + dwarf[i].a;
    }
    for(int i=0;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            dp[i][j] = inf;
        }
    }
    return;
}

void solve()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            dp[i][j] = MIN(dp[i-1][j] - dwarf[i].a , MAX(dp[i-1][j-1] , h - sum[i] - dwarf[i].b));
        }
    }
    for(int i=n;i>=0;i--)
    {
        if(dp[n][i] <= 0)
        {
            printf("%d\n",i);
            break;
        }
    }
    return;
}

int main()
{
    while(~scanf("%d",&n))
    {
        read();
        solve();
    }
    return 0;
}
时间: 2024-10-05 19:22:03

HDU 4314 Save the dwarfs (DP) ---转载的相关文章

hdu 4804 Campus Design 轮廓线dp

题意: 给出一个n*m的01矩阵,其中要求把矩阵里面的1用1*1或1*2的砖块铺满,矩阵里面的0为障碍物,问使用1*1的砖块数>=c && <=d 的方案有多少种. 限制: 1 <= n <= 100; 1 <= m <= 10; 1 <= c <= d <= 20; 思路: 因为 1 <= m <= 10 所以可以采用轮廓线dp, 具体状态解释在代码中说明. /*hdu 4804 Campus Design 轮廓线dp 题

[ACM] hdu 3853 LOOPS (概率DP,递推)

LOOPS Problem Description Akemi Homura is a Mahou Shoujo (Puella Magi/Magical Girl). Homura wants to help her friend Madoka save the world. But because of the plot of the Boss Incubator, she is trapped in a labyrinth called LOOPS. The planform of the

hdu 3555 Bomb(数位dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 题目大意:就是给你一个数n,判断从0到n有多少个数含有数字49...... 是不是觉得跟hdu2089很相似呀... 思路:跟hdu2089一样的,注意给出的数比较大,所以这儿用__int64  .... code: #include<cstdio> #include<iostream> #include<cstring> #include<algorithm&

HDU 1231 最大连续子序列 DP题解

典型的DP题目,增加一个额外要求,输出子序列的开始和结尾的数值. 增加一个记录方法,nothing special. 记录最终ans的时候,同时记录开始和结尾下标: 更新当前最大值sum的时候,更新开始节点. const int MAX_N = 10001; long long arr[MAX_N]; int N, sta, end; long long getMaxSubs() { long long sum = 0, ans = LLONG_MIN; int ts = 0; for (int

[ACM] hdu 2089 不要62(数位Dp)

不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 19043    Accepted Submission(s): 6442 Problem Description 杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer). 杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就

HDU 4901 The Romantic Hero(DP)

HDU 4901 The Romantic Hero 题目链接 题意:给定一个序列,要求找一个分界点,然后左边选一些数异或和,和右边选一些数且和相等,问有几种方法 思路:dp,从左往右和从右往左dp,求出异或和且的个数,然后找一个分界点,使得一边必须在分界点上,一边随意,然后根据乘法原理和加法原理计算 代码: #include <cstdio> #include <cstring> typedef __int64 ll; const int N = 1024; const int

HDU 1160 FatMouse&#39;s Speed DP题解

本题就先排序老鼠的重量,然后查找老鼠的速度的最长递增子序列,不过因为需要按原来的标号输出,故此需要使用struct把三个信息打包起来. 查找最长递增子序列使用动态规划法,基本的一维动态规划法了. 记录路径:只需要记录后继标号,就可以逐个输出了. #include <stdio.h> #include <algorithm> using namespace std; const int MAX_N = 1005; struct MouseSpeed { int id, w, s; b

HDU 2089 不要62(数位DP,三种姿势)

HDU 2089 不要62(数位DP,三种姿势) ACM 题目地址:HDU 2089 题意: 中文题意,不解释. 分析: 100w的数据,暴力打表能过 先初始化dp数组,表示前i位的三种情况,再进行推算 直接dfs,一遍搜一变记录,可能有不饥渴的全部算和饥渴的部分算情况,记录只能记录全部算(推荐看∑大的详细题解Orz) 代码: 1. 暴力 (以前写的) /* * Author: illuz <iilluzen[at]gmail.com> * File: 2089_bf.cpp * Create

HDU 2084 数塔 --- 入门DP

HDU 2084 数塔 从下往上递推,状态转移方程 dp[i][j] = max( dp[i+1][j], dp[i+1][j+1]) + a[i][j]; /* HDU 2084 数塔 --- 入门DP */ #include <cstdio> const int N = 105; int dp[N][N]; int MAX(int a, int b){ return a > b ? a : b; } int main() { #ifdef _LOCAL freopen("D