思路: 此题是一道完全背包问题,完全背包相对于01背包就是每项物品可以在容量限制内无限叠加,再加上此题是求装入物品的最小值,因此可得:
DP状态转移方程:dp[ i ] = min(dp[j], dp[j - w[i]] + v[i])
注意:
1:因为要比较出最小值储存,因此dp数组一开始应该设置一个无穷大值,建议使用0x3f3f3f3f,因为0x3f3f3f3f在十进制情况下大于,而一般测试样例不超过此值。
2:由于dp[ 0 ]要为后面dp值的生成做铺垫,所以不能设置为无穷,应设置为0
3:输入w[ i ]和v[ i ]时不要弄反
理解原理:
举一个样例输入:
1
1 10
3
2 2
2 3
3 4
那么dp数组的变化应为(M代表无穷)
dp[] 1 2 3 4 5 6 7 8 9
0: M M M M M M M M M
1: M 2 M 4 M 6 M 8 M
2: M 2 2 4 4 4 6 6 6
3: M 2 2 3 4 5 5 6 6
#include<iostream>
#include<string>
#define MAX 0x3f3f3f3f
using namespace std;
int min(int i, int j);
int main() {
int t;
cin >> t;
while (t--) {
int e, f, kind, * v, * w, * dp;
cin >> e >> f >> kind;
f -= e;
v = new int[kind + 1];
w = new int[kind + 1];
dp = new int[f + 1];
memset(dp, MAX, sizeof(int) * (f + 1));
dp[0] = 0;
for (int i = 1; i <= kind; i++) {
cin >> v[i] >> w[i];
}
for (int i = 1; i <= kind; i++) {
for (int j = w[i]; j <= f; j++) {
dp[j] = min(dp[j], dp[j - w[i]] + v[i]);
}
}
if (dp[f] == MAX) {
printf("This is impossible.\n");
}
else {
printf("The minimum amount of money in the piggy-bank is %d.\n", dp[f]);
}
}
return 0;
}
int min(int i, int j) {
return(i < j) ? i : j;
}