先看满与不满的代码区别,
不装满只求最大价值:将第0行全部初始化为0就完事
装满且价值尽可能大:将第0行第一个元素初始化为0,这一行的其他元素赋值为-∞(-999也行,主要保证其绝对值大于全部物品的价值之和即可) f[0]=0; f[1~n]= -∞
思路
为什么:
对于装满,在没有物品装入的时候,只有容量为0才能装满背包,而容量为正数的时候不可能装满(没有物品塞进去怎么装都不会满)。
因此这里f[1~n]初始化 为-∞相当于标记不能装满。
然后推导第1行,
显然你唯一能填入的正数是刚好塞进第1个物件,因为这条式子dp[j]=max(dp[j],dp[j-weigh[i]]+value[i]);第0行只有1个0,其他都是很负的负数,只有刚好装进第1个物件才有j-weigh[i]等于0,此时dp[j-weigh[i]]才等于0,这个dp[j-weigh[i]]+value[i]才可能为正数,。一旦j-weigh[i]大于0就意味着没塞满,dp[j-weigh[i]]必然为负数,无论如何dp[j-weigh[i]]+value[i]都是负数,这里相当于又标记了一次(没塞满)
到了第2行,
若容量足以再容纳第2件物件,只有当dp[j-weigh[i]]+value[i]为非负数才意味着刚好塞满,因为同上,只有dp[j-weigh[i]]为非负数,dp[j-weigh[i]]+value[i]才可能为非负数,显然j-weigh[i]等于第1件物件重量时dp[j-weigh[i]]为非负数,以此类推
/*问题描述:有编号分别为a,b,c,d,e的五件物品,
它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,
每件物品数量只有一个,
现在给你个承重为10的背包,
如何让背包塞满且里装入的物品具有最大的价值总和?答案是15*/
/*
v w
输入
6 2
3 2
5 6
4 5
6 4
*/
#include<stdio.h>
int max(int a,int b)
{
if(a>b)
{
return a;
}
else
{
return b;
}
}
int main()
{
int value[30],weigh[30],dp[80],maxn=0;
int i,j;
for(i=1;i<=5;i++)
{
scanf("%d %d",&value[i],&weigh[i]);
}
weigh[0]=0;
for(i=0;i<=5;i++)//i负责滚动行的次数,j负责容量变化
{
for(j=10;j>=weigh[i];j--)
{
if(j==0)
{
dp[j]=0;//初始化
}
if(j!=0&&i==0)
{
dp[j]=-999;//初始化
}
if(j!=0&&i!=0)
{
dp[j]=max(dp[j],dp[j-weigh[i]]+value[i]);
}
if(dp[j]>maxn)
{
maxn=dp[j];
}
}
}
printf("%d",maxn);
return 0;
}