看了背包九讲后找来的完全背包入门题目。。
附上题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1114
该题跟之前的背包问题有点不同在于他要求的是最小值并且要求装满整个背包。。。
所以我们在初始化的时候就要注意应该将f[0]初始化为0,其他的都要初始化为正无穷。。。
那如果最后结果是正无穷那么就是不可能装满。
这个在背包九讲中有提到初始化的问题,讲的还是蛮容易理解的。
还有就是完全背包与01背包的差别在于一维写法的遍历顺序,01背包为逆序,这样才能保证该物品一定没有被拿过,完全背包为正序,这样就确保了这个物品可能被拿过也可能没有被拿过,正符合完全背包的题意。
二维下的状态转移方程:F[i,v] = max (F[i − 1,v],F[i,v − C i ] + W i )
一维的状态转移方程:F[v] = max {F[v],f[v − C] + W}
先给出二维解法;
#include<cstdio>
#include<cstring>
#include<climits>
#define INF 1000000001
int f[510][10000];
int w[510];
int c[510];
int min (int a,int b)
{
return (a>b) ? b:a;
}
int main ()
{
int t;
scanf("%d",&t);
while (t--)
{
//memset(s,0,sizeof(s));
int a,b;
scanf("%d%d",&a,&b);
int V = b - a;
int type;
scanf("%d",&type);
int i,j;
for(i = 0;i <= type;i++)
f[i][0] = 0;
for(i = 0;i <= V;i++)
f[0][i] = INF;
for(i = 1;i <= type;i++)
scanf("%d%d",&w[i],&c[i]);
for(i = 1;i <= type;i++)
for(j = 1;j <= V;j++)
{
if(j < c[i])
f[i][j] = f[i-1][j];
else
f[i][j] = min(f[i-1][j],f[i][j-c[i]]+w[i]);
}
if(f[type][V] != INF)
printf("The minimum amount of money in the piggy-bank is %d.\n",f[type][V]);
else printf("This is impossible.\n");
}
return 0;
}
一维的应该更加重要自己要好好掌握:
#include<cstdio>
#define INF 1000000001
int w[510];
int c[510];
int f[10010];
int min (int a,int b)
{
return (a > b)? b:a;
}
int main ()
{
int t;
scanf("%d",&t);
while(t--)
{
int a,b;
scanf("%d%d",&a,&b);
int vm = b - a,n;
scanf("%d",&n);
int i,j;
for(i = 1;i <= n;i++)
scanf("%d%d",&w[i],&c[i]);
for(i = 1;i <= vm;i++)
f[i] = INF;
f[0] = 0;
for(i = 1;i <= n;i++)
for(j = c[i];j <= vm;j++)
f[j] = min(f[j],f[j-c[i]]+w[i]);
if(f[vm] != INF)
printf("The minimum amount of money in the piggy-bank is %d.\n",f[vm]);
else printf("This is impossible.\n");
}
return 0;
}