LuoguP4823 [TJOI2013]拯救小矮人

LuoguP4823 [TJOI2013]拯救小矮人

Description

链接

题目大意:n个人每个人有身长A和臂长B,如果满足A1+A2+……An+Bn>=H 则第N个人可以爬出洞

怎样安排顺序使最多人爬出洞。

Solution

可以考虑一个显然的贪心:身高+臂长越长的人越后面出去

所以按身高加臂长排序,让越难出去的先出去。

但是因为出去是由身高加臂长两个因素决定的

所以不代表身高加臂长长的人一定在小的人后出去

举个例子,当H=9 如果a1 = 5 , b1 = 2 ,a2 = 2 ,b2 = 1

那么反而要身高加腿长更小的当人梯

即需要考虑奉献自己的情况

所以考虑DP

令DP[i]表示前面更容易走的走了i个人后剩下的最大高度

转移方程见代码

#include<bits/stdc++.h>

using namespace std;

inline int read()
{
    int f = 1 ,x = 0;
    char ch;
    do
    {
        ch = getchar();
        if(ch == '-') f = -1;    
    }while(ch<'0'||ch>'9');
    do
    {
        x = (x<<3) + (x<<1) + ch - '0';
        ch = getchar();    
    }while(ch>='0'&&ch<='9');
    return f*x;    
} 

const int MAXN = 100000 + 10;

struct ZHENGJUNSHIDASHABI
{
    int a;
    int b;
    friend bool operator < (ZHENGJUNSHIDASHABI a1,ZHENGJUNSHIDASHABI a2)
    {
        if(a1.a+a1.b == a2.a + a2.b) return a1.a<a2.a;
        else return a1.a+a1.b<a2.a+a2.b;
    }
}p[MAXN];

int n;
int H;
int dp[MAXN];

int main()
{
    n = read();
    for(int i=1;i<=n;i++) p[i].a = read(),p[i].b = read(),dp[0]+=p[i].a;
    sort(p+1,p+n+1);
    H = read();
    for(int i=1;i<=n;i++) dp[i] = -(1<<30);
    for(int i=1;i<=n;i++)
    {
        for(int j=i;j>=1;j--)
        {
            if(dp[j-1] + p[i].b >= H)
            {
                dp[j] = max(dp[j] , dp[j-1] - p[i].a);
            }
        }
    }
    int res = 0;
    for(int i=n;i>=0;i--) if(dp[i] >= 0){res = i;break;}
    cout << res << endl;
}

 

posted @ 2020-07-16 19:49  wlzs1432  阅读(131)  评论(0编辑  收藏  举报