问题描述:有n个物品,第i个物品的重量为w[i],价值为v[i]。选一些物品放入背包中,使背包内物品总重量恰好为W的前提下,总价值尽量大。
输入:有多组测试数据,每组数据第一行为2个正整数,分别代表物品的个数n和背包的容量W,接下来的n行,每行2个正整数,用空格隔开,分别代表物品的重量w和价值v, 当n、W同时为0时结束测试,此时不输出。所有输入数字的范围大于等于0,小于等于1000。
输出:若能恰好放满背包则输出最大总价值,否则输出No,每组输出占一行。
解题思路:与0-1背包(一)类似,设f[i][j]表示前i(1<=i<=n)个物品选择放入容量为j(0<=j<=n)的背包中能恰好放满时达到的最大总价值,并用f[i][j]=-1表示前i个物品不能恰好把容量为j的背包放满,因此对于第i个物品能不能放入容量为j的背包中不仅取决于j>=w[i],还要满足f[i-1][ j-w[i] ]!=-1;
故: if(j>=w[i]&&f[i][j-w[i]]!=-1)
{ f[i][j]=max( f[i-1][j] , f[i-1][ j-w[i] ]+w[i] ) }
else
{ f[i][j]=f[i-1][j] }
当然仍然可以像0-1背包(一)一样用滚动数组来优化空间。
源代码如下:
#include <stdio.h>
#include <string.h>
#define maxn 1001
int f[maxn];
int main()
{
int n,W,w,v,i,j;
while(scanf("%d%d",&n,&W)&&(n+W))
{
memset(f,-1,sizeof(f)); //注意memset()只能把数组元素全赋值为0或-1
f[0]=0; //当还没有物品时只有容量为0的背包可以放满,且最大价值为0,故f[j]初始化为f[0]=0 , f[1.....n]=-1
for(i=1;i<=n;i++)
{
scanf("%d%d",&w,&v);
for(j=W;j>=w;j--)
if(f[j-w]!=-1&&f[j-w]+v>f[j])
f[j]=f[j-w]+v;
}
if(f[W]!=-1)
printf("%d\n",f[W]);
else
printf("No\n");
}
return 0;
}