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;
}