CF1862F Magic Will Save the World
CF1862F Magic Will Save the World
这道题目要求使用两种魔法(水魔法和火魔法)消灭一组怪物,每个怪物有不同的强度,而魔法的获得速度也不同。通过贪心策略,将尽可能多的水魔法用于消灭怪物,并使用 01 背包预处理得到最大水魔力消耗,然后判断剩余怪物是否能够被火魔法消灭,最终输出最少需要的时间。
题目大意
你有两个魔法,水魔法和火魔法。每秒你分别能获得 $s,f$ 点对应的魔力。现在有 $n$ 个怪物,每个怪物的强度为 $s_i$。强度为 $s_i$ 的怪物需要 $s_i$ 点魔力的任意魔法消灭。施法不耗任何时间,请问最少几秒后可以杀完全部的怪物?
思路
显然放到最后一起杀更方便处理,问题转变成判断 $curr_s,curr_f$ 的水魔法和火魔法能不能杀光全部的怪物。消灭怪物所需的能量总和 $sum_s$ 是固定的,贪心的考虑,我们需要让 $curr_s$ 的水魔法尽可能的使用得更多去消灭怪兽(这个操作可以用 01 背包预处理好),然后判断剩下的怪兽能不能被火能量消灭。
一开始写了一个裸的二维 01 背包,不出意外的 MLE 了,之后优化成一维背包竟然一发就过了。
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
int w, f, n, sum_s, cnt, s[110],
dp[1000010]; // dp[i][j]表示用j个水打前i个,最多能用掉多少水
void solve() {
sum_s = cnt = 0;
cin >> w >> f >> n;
rep(i, 1, n) {
cin >> s[i];
sum_s += s[i];
}
rep(j, 1, sum_s) dp[j] = 0;
rep(i, 1, n) {
per(j, sum_s, 1) {
if (j >= s[i])
dp[j] = max(dp[j], dp[j - s[i]] + s[i]);
}
}
int curr_w = 0, curr_f = 0;
while (++cnt) {
curr_w += w, curr_f += f;
if (curr_f >= sum_s - dp[min(curr_w, sum_s)]) {
break;
}
}
cout << cnt << endl;
}
This post is licensed under CC BY 4.0 by the author.