口袋妖怪征服标题:
《精灵宝可梦》讲述了小智和他的搭档皮卡丘的冒险故事。
三天后,小智和皮卡丘来到了精灵狩猎场,那里有很多稀有的野生宝可梦。
小智也想制服一些神奇宝贝。
然而,野生小精灵并不那么容易捕捉。
对于每个野生宝可梦,小智可能需要使用多个精灵球来捕捉它,而在捕捉过程中,野生宝可梦也会对皮卡丘造成一定的伤害(从而降低皮卡丘的体力)。
当皮卡丘体力大于等于0时,小智必须结束狩猎(因为他需要治疗皮卡丘),提示皮卡丘体力大于等于0的野精灵不会被小智制服.
当小智用完精灵球时,狩猎就结束了。
我们假设当小智遇到野精灵时,他有两个选择:接受或离开。
如果小智选择捕捉,那么他肯定会扔出能捕捉到宝可梦的精灵球萌芽精灵大冒险,皮卡丘肯定会受到相应的伤害;如果他选择离开,那么小智不会失去精灵球,皮卡丘不会失去体力。
小智有两个目标:主要目标是捕捉尽可能多的野生宝可梦;如果可以捕获的神奇宝贝数量相同,小智希望皮卡丘受到的伤害更少(剩余的耐力越多),因为他们必须继续冒险。
现在我们知道了 的数量和皮卡丘的初始体力,每个 需要捕捉的 的数量以及捕捉过程中对皮卡丘造成的伤害。
请问,小智应该如何选择征服哪个精灵来实现自己的目标?
输入格式:
输入数据的第一行包含三个整数:N、M、K萌芽精灵大冒险,分别代表精灵球的数量、皮卡丘的初始体力和野生精灵的数量。
在下面的K行中,每行代表一个野生精灵,包括两个整数:捕捉精灵所需的精灵球数量,捕捉过程中对皮卡丘造成的伤害。
输出格式:
输出为一行,包含两个整数:C和R,分别表示捕获的宝可梦最大数量为C,捕获C宝可梦时皮卡丘剩余体力值最多为R。
数据范围:
输入示例1:
10 100 5
7 10
2 40
2 50
1 20
4 20
示例输出 1:
3 30
输入样本 2:
10 100 5
8 110
12 10
20 10
5 200
1 110
示例输出 2:
0 100
说明:
01 单肩包问题,不同的是体积有两部分:精灵球的数量和皮卡丘的物理值,数值是捕获的精灵数量。
状态表示:
f[i][j][k]表示只有前i个,消耗的个数不超过j,皮卡丘的体力不超过k的最大值。
捕获最多的精灵是 f[K][N][M]。求最小代价,求最小的 f[k][N][t]==f[K][N][M]。
代码:
#include
#include
#include
using namespace std;
const int N = 1010, M = 510;
int n, V1, V2;
int f[N][M];
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; k > v2; k --) {
f[j][k] = max(f[j][k], f[j - v1][k - v2] + 1);
}
}
}
cout << f[V1][V2] << " ";
int k = V2;
while (k > 0 && f[V1][V2] == f[V1][k]) k --;
cout << V2 - k << endl;
return 0;
}