[Luogu P4823] [BZOJ 3174] [TJOI2013]拯救小矮人

版权声明:欢迎转载蒟蒻博客,但请注明出处:blog.csdn.net/lpa20020220 https://blog.csdn.net/LPA20020220/article/details/82622787

洛谷传送门

BZOJ传送门

题目描述

一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯。即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以碰到陷阱口。

对于每一个小矮人,我们知道他从脚到肩膀的高度 A i ,并且他的胳膊长度为 B i 。陷阱深度为 H

如果我 们利用矮人 1 ,矮人 2 ,矮人 3 ,。。。矮人 k 搭一个梯子,满足 A 1 + A 2 + A 3 + . . . . + A k + B k   H ,那么矮人 k 就可以离开陷阱逃跑了,一 旦一个矮人逃跑了,他就不能再搭人梯了。

我们希望尽可能多的小矮人逃跑, 问最多可以使多少个小矮人逃跑。

输入输出格式

输入格式:

第一行一个整数 N , 表示矮人的个数,接下来 N 行每一行两个整数 A i B i ,最后一行是 H 。( A i B i H 10 5

输出格式:

一个整数表示对多可以逃跑多少小矮人

输入输出样例

输入样例#1:

2
20 10
5 5
30

输出样例#1:

2

输入样例#2:

2
20 10
5 5
35

输出样例#2:

1

说明

30%的数据 N 200
100%的数据 N 2000

解题分析

d p [ i ] 表示跑了 i 个人后剩下人的总身高最大为多少。 对于最上面的一个小矮人, 它的逃生能力就是 A i + B i , 显然随着逃生人数的增加需要的 A i + B i 会增加, 所以我们先尝试让 A i + B i 较小的人先走, 并尝试更新 d p [ i ] 使得其尽量大即可。

代码如下:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cctype>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 2050
template <class T>
IN void in(T &x)
{
    x = 0; R char c = gc;
    for (; !isdigit(c); c = gc);
    for (;  isdigit(c); c = gc)
    x = (x << 1) + (x << 3) + c - 48;
}
struct INFO {int bod, arm, tot;} dat[MX];
IN bool operator < (const INFO &x, const INFO &y)
{return x.tot < y.tot;}
int dp[MX], h, dot, ans;
int main(void)
{
    in(dot);
    std::memset(dp, -1, sizeof(dp)); dp[0] = 0;
    for (R int i = 1; i <= dot; ++i)
    in(dat[i].bod), in(dat[i].arm), dat[i].tot = dat[i].bod + dat[i].arm, dp[0] += dat[i].bod;
    in(h);
    std::sort(dat + 1, dat + 1 + dot);
    for (R int i = 1; i <= dot; ++i)
    {
        for (R int j = ans; ~j; --j)
        if(dp[j] + dat[i].arm >= h) dp[j + 1] = std::max(dp[j + 1], dp[j] - dat[i].bod);
        if(dp[ans + 1] >= 0) ++ans;
    }
    printf("%d", ans);
}

猜你喜欢

转载自blog.csdn.net/LPA20020220/article/details/82622787