CF1203F1 Complete the Projects (easy version) 题解 贪心

题目链接:https://www.luogu.com.cn/problem/CF1203F1

题目大意:

\(n\) 个任务,初始有 \(r\) 点体力。

完成第 \(i\) 个任务前至少需要 \(a_i\) 点体力,完成第 \(i\) 个任务会增加 \(b_i\) 的体力(\(b_i\) 可能为负)。

任意时刻体力不能为负。

问:是否存在一个完成任务的顺序,使得能完成所有任务?

解题思路:

优先选择 \(b_i \ge 0\) 的,因为这样能使 \(r\) 增大。

对于 \(b_i \ge 0\) 的情况,优先选择 \(a_i\) 小的。\(\Rightarrow\)\(r\) 变大了才能选 \(a_i\) 更大的。

对于 \(b_i \lt 0\) 的情况,这个时候考虑 \((a_1, b_1), (a_2, b_2), \ldots\) 的顺序选,则会发现:

  • 若初始的体力是 \(a_1\)
  • 则选择 \((a_1, b_1)\) 之后体力降为 \(a_1 + b_1\)(因为 \(b_1 \lt 0\)
  • 然后选择 \((a_2, b_2)\),会发现此时要求 \(a_1 + b_1 \ge a_2\)
  • ……

然后会发现如下的一个规律:

\(a_1 \gt a_1 + b_1 \ge a_2 \gt a_2 + b_2 \ge a_3 \gt a_3 + b_3 \ge a_4 \ldots\)

发现:

\(a_1 + b_1 \gt a_2 + b_2 \gt \ldots\)

所以当 \(b_i \gt 0\) 是,按 \(a_i + b_i\) 从大到小排序。

在中间过程中有不满足 \(r \ge a_i\) 的情况就是 "NO"。

示例程序:

#include <bits/stdc++.h>
using namespace std;
int n, r;
struct Node {
    int a, b;
} a[110];

bool cmp(Node a, Node b) {
    if (a.b >= 0 && b.b >= 0)
        return a.a < b.a;
    if (a.b < 0 && b.b < 0)
        return a.a + a.b > b.a + b.b;
    return a.b >= 0;
}

int main() {
    cin >> n >> r;
    for (int i = 0; i < n; i++) cin >> a[i].a >> a[i].b;
    sort(a, a+n, cmp);
    for (int i = 0; i < n; i++) {
        if (r < max(a[i].a, -a[i].b)) {
            cout << "NO" << endl;
            return 0;
        }
        r += a[i].b;
    }
    cout << "YES" << endl;
    return 0;
}
posted @ 2022-12-14 12:36  quanjun  阅读(13)  评论(0编辑  收藏  举报