原题链接:https://www.acwing.com/problem/content/description/1024/
难度:简单
涉及知识点:二维费用01背包
题意分析
简化地,小智有 V 1 V1 V1 个精灵球,皮卡丘的初始体力值为 V 2 V2 V2,一共有 n n n 只野生小精灵。收服第 i i i 只精灵球,需要耗费 v 1 i v1_i v1i 个精灵球和 v 2 i v2_i v2i 点皮卡丘的体力值。特别注意地,皮卡丘的体力值不能小于等于0,也就是说,和一般的01背包问题不同,我的费用只能从 V 2 − 1 V2-1 V2−1 开始枚举。求最多可以收服的小精灵个数 C C C 和收服 C C C 只小精灵时皮卡丘的最大剩余体力。
分析与解决
这是典型的二维费用01背包问题,不过题面冗余杂长,需要提炼有用的关键信息,上一项的题意分析便是该题的简要题意。
对于第一问,直接套用板子,对于第二问,考虑从
k
=
V
2
−
1
k=V2-1
k=V2−1开始从大到小枚举所耗费的体力,当遇到
k
−
1
k-1
k−1 的体力已经无法捕捉到
C
C
C 只小精灵时,停止枚举,当前的
k
k
k 就是捕捉
C
C
C 只小精灵最少需要耗费的皮卡丘体力值。最后用初始体力值减去
k
k
k 即可。
AC代码
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 1100, M = 550;
int V1, V2, n;
int f[N][N];
int main()
{
cin >> V1 >> V2 >> n;
for (int i = 0; i < n; i++)
{
int v1, v2;
cin >> v1 >> v2;
for (int j = V1; j >= v1; j--)
{
for (int k = V2 - 1; k >= v2; k--)
{
f[j][k] = max(f[j][k], f[j - v1][k - v2] + 1);
}
}
}
cout << f[V1][V2 - 1] << " ";
int k = V2 - 1;
while (k > 0 && f[V1][k - 1] == f[V1][V2 - 1]) k--;
cout << V2 - k;
return 0;
}