题目大意:
ACM小组有一个存钱罐,存钱罐一旦打破就不能复原,现在我们可以得到存钱罐里钱币的重量,给你每种钱币的重量以及价值,求存钱罐里至少有多少钱。
题目思路:
这是一个比较明显的背包问题,钱币的重量相当于占用的体积,背包总体积就是已知的存钱罐里钱币的重量。因每种钱币有其相应的价值,我们要求出把背包装满的情况下,能达到的最小价值。
跟普通的完全背包唯一的不同就是大前提时要满足给出的存钱罐里的重量,也就是说背包必须装满;对于这种问题,我们可以通过改变初始化的值来解决:
①要求背包必须装满 求最大值
把f[0]初始化为0,其余初始化为
②要求背包必须装满 求最小值
把f[0]初始化为0,其余初始化为
原因:
初始化数组事实上就是在没有任何物品可以放入背包时的合法状态。如果要求背包恰好装满,那么此时只有容量为0的背包可以在什么也不装且价值为0的情况下被“恰好装满”,其它容量的背包均没有合法的解,属于未定义状态,应该被赋值为或者;如果背包并非必须装满,那么任何容量的背包都有一个合法解“什么也不装”,即0,所以可以把它们全部初始化为0。
这样一来就跟完全背包没有什么区别了~
题目代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define INF 999999
#define maxn 10005
using namespace std;
int f[maxn];//存钱罐重量为j
int val,w;
int main(void)
{
int t;
int e,ff,wei;
int n;
scanf("%d",&t);
while(t--)
{
f[0]=0;
scanf("%d%d",&e,&ff);
int wei=ff-e;
scanf("%d",&n);
for(int i=1;i<=wei;i++)
{
f[i]=INF;//初始化为无穷大
}
for(int i=0;i<n;i++)//完全背包的常规操作
{
scanf("%d%d",&val,&w);
for(int j=w;j<=wei;j++)
{
f[j]=min(f[j],f[j-w]+val);
}
}
/*
for(int i=0;i<n;i++)
{
for(int j=w[i];j<=wei;j++)
{
f[j]=min(f[j],f[j-w[i]]+val[i]);
//printf("j: %d f[j]: %d\n",j,f[j]);
}
}
*/
if(f[wei]==INF)
printf("This is impossible.\n");
else
printf("The minimum amount of money in the piggy-bank is %d.\n",f[wei]);
}
return 0;
}
呼呼