完全背包。求最小价值(恰好装满)。
有一个存钱罐,里面有很多个硬币,硬币分为很多种类,每种有各自的重量和价值。现在给你每种硬币的信息,和这个存钱罐存的重量,让你猜测里面硬币的最小价值。
这个题让求最小价值,所以肯定是必须装满了(结合这个题意也必须是重量恰好相等)。最小值一定是必须装满,但必须装满不一定是求最小值。
必须装满的话,初始化置为-INF
就可以了,但是还是个最小值问题,最小值问题是min
函数,所以初始化不可能的情况为+INF
。然后最后判断dp[V]
,如果正好等于+INF
就说明不可能恰好装满。(为什么最后还是正好等于+INF
?因为 min(INF,INF+p[i]) = INF
。如果是最大值的恰好装满就要判断dp[V]
是否小于0
)
另外,因为是恰好装满问题,我感觉用不了那个优化,就是对物品预处理,删一些物品的那个优化。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <string>
using namespace std; // 完全背包 求最小值(恰好装满)
const int MAXN = 501;
const int INF = 1e9;
int dp[10001];
int p[MAXN];
int w[MAXN];
int N, V, T;
void init()
{
fill(dp + 1, dp + V + 1, INF); // 是求最小值,所以不可能情况的初始值设为 +INF
dp[0] = 0;
}
int main()
{
int a, b;
scanf("%d", &T);
for (; T--;)
{
scanf("%d%d", &a, &b);
V = b - a;
init();
scanf("%d", &N);
for (int i = 1; i <= N; i++)
scanf("%d%d", &p[i], &w[i]);
for (int i = 1; i <= N; i++)
{
for (int j = w[i]; j <= V; j++) // 完全背包,正向枚举
{
dp[j] = min(dp[j], dp[j - w[i]] + p[i]);
}
}
if (dp[V] == INF) printf("This is impossible.\n");
else printf("The minimum amount of money in the piggy-bank is %d.\n", dp[V]);
}
return 0;
}