• 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
    ",i);
                break;
            }
        }
        return;
    }
    
    int main()
    {
        while(~scanf("%d",&n))
        {
            read();
            solve();
        }
        return 0;
    }
  • 相关阅读:
    BZOJ 1007 HNOI2008 水平可见的直线
    BZOJ 3155 Preprefix sum
    BZOJ 1036 ZJOI2008 树的统计
    BZOJ 1096 ZJOI2007 仓库建设
    BZOJ 1012 JSOI2008 最大数maxnumber
    BZOJ 1001 狼抓兔子
    BZOJ 1046 HAOI 上升序列
    [POI2015]PUS
    [NOI2011]道路修建
    POI 2015 KIN
  • 原文地址:https://www.cnblogs.com/Ritchie/p/5754449.html
Copyright © 2020-2023  润新知