题意:
告诉你背包的容量N,和 M 件物品分别各自的体积和质量, 求背包剩余容量为0(即刚好填满)的时候,最小的质量。
3 三个测试样例
10 110 //N = 110 - 10 = 100 题意为金元宝总质量110 金元宝自己的质量为10 所以物品的质量就是100
2 // 两件物品
1 1 //质量为1 体积为1
30 50 // 质量为30 体积为50
所以放两个体积50的就满了 质量最少 为 60
所以输出 The minimum amount of money in the piggy-bank is 60.
1 6
2
10 3
20 4
第三个例子同理 背包体积为5 物品体积为3 4 ,肯定放不满,所以输出不可能。
分析:
这个题目是完全背包的模板题,可完全背包非常类似于01背包问题,所不同的是每种物品有无限件。也就是从每种物品的角度考虑,与它相关的策略已并非取或不取两种,而是有取0件、取1件、取2件……等很多种。如果仍然按照解01背包时的思路,令f[i][v]表示前i种物品恰放入一个容量为v的背包的最大权值。仍然可以按照每种物品不同的策略写出状态转移方程,像这样:
f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0<=k*c[i]<=v}
模板是这样的:
for i=1..N
for v=0..V
f[v]=max{f[v],f[v-cost]+weight}
所以只需要套一下模板,注意初始化必须要大一点 99999会WA
求背包最大重量,初始化0 ,状态转移方程取max
求背包最小重量,初始化+∞,状态转移方程取min
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int minn(int x, int y) {
return x < y ? x : y;
}
const int INF = 99999999;
struct ss
{
int zhong;
int ti;
}a[502];
int dp[10002];
int main()
{
int t;
scanf_s("%d", &t);
while (t--) {
int n, m;
scanf_s("%d%d", &n, &m);
n = m - n;
scanf_s("%d", &m);
for (int i = 0; i < m; i++) {
scanf_s("%d%d", &a[i].zhong, &a[i].ti);
}
fill(dp, dp + 10002, INF);
dp[0] = 0;
for (int i = 0; i < m; i++) {
for (int j = a[i].ti; j <= n; j++) {
dp[j] = minn(dp[j], dp[j - a[i].ti] + a[i].zhong);
}
}
if (dp[n] == 99999999)
puts("This is impossible.");
else
printf("The minimum amount of money in the piggy-bank is %d.\n", dp[n]);
}
return 0;
}