好像是和官方题解不同的做法???没认真看。
显然的,对于前 iii 个怪物,如果存在一种方法可以打死这些怪物,那么答案就可以对 iii 取 max\maxmax。于是就变成了如何判断对于前 iii 个怪物能不能全部打死。
考虑把视角放到 HHH 和 WWW 上。对于一种把怪物的某个前缀全部打死的方案,显然是选择一些消耗 HHH,其他的消耗 WWW。而且 HHH 和 WWW 都不能 <0<0<0。
考虑枚举 iii 并枚举 HHH 消耗了多少,现在复杂度是 O(NH)O(NH)O(NH) 的。容易想到,对于两种不同的可能方案,如果它们对 HHH 的消耗相同,则对 WWW 消耗少的方案更好。也就是选择使用 aaa 消耗 HHH 的下标数列中每一个数对应的 bbb 的和最大。
于是就容易想到使用背包 dp,将 HHH 作为背包容量,iii 作为物品的数量,aaa 作为体积,bbb 作为收益。显然背包 dp 的时间复杂度也是 O(NH)O(NH)O(NH) 的,而且还可以对于 HHH 消耗的值 O(1)O(1)O(1) 判断是否合法。
然后我们就可以快速判断了。代码很短。
#include <bits/stdc++.h>
using namespace std;
const int N = 3010;
int dp[N][N];
int a[N], b[N];
int n, x, y;
int main() {
cin >> n >> x >> y;
int sum = 0;
int ans = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i] >> b[i];
sum += b[i];//先记录一下前缀和
for (int j = 0; j <= x; j++)
dp[i][j] = dp[i - 1][j];
for (int j = a[i]; j <= x; j++)
dp[i][j] = max(dp[i][j], dp[i - 1][j - a[i]] + b[i]);//跑背包,但是我懒得用滚动数组了
for (int j = 0; j <= x; j++)
if ((sum - dp[i][j]) <= y)
ans = max(ans, i);//直接计算是否存在满足要求的
}
cout << ans << endl;
return 0;
}
貌似我是题解里面最短的代码???那很不错了。