主要写背包问题最优算法的个人注释,暂时先写0-1背包,完全背包,多重背包,详细基础看https://mp.youkuaiyun.com/postedit
0-1 背包:
weight 物体重量
value 物体价值
w背包可承受上限
for i=1;i<=n;i++
for j=w;j>=1;j--
if(j>weight[i])
bag[j]=max(bag[j],bag[j-wight[i]]+value[i])
else
bag[j]=bag[j];
注:
1 第二重循环从w开始,原因是0-1背包只有放当前物体与不放,若从1开始,一旦j开始大于当前物体重量后,前面数据可能被覆盖,后面再调用前面数据时,已经无法做到当前物体与其他物品合放,用样例模拟一下,就能明白。
2 涉及到放满背包时,bag[0],初始化为0,其他为一个负的极大值,这样,只有当物体重量刚好等于当前j,即给定j当前物品可以将其装满,就放入,后面的物体,给定j,只能刚好等于其重量或者与之前物品合放刚好等于j。
完全背包
for i=1;i<=n;i++
for j=1;j<=weight;j++
if j>=weight[j]
bag[j]=max(bag[j],bag[j-weight[j]]+value[i])
else
bag[j]=bag[j];
注:
无限物体,解决方法是对于每一步能放则放,然后进行比较,比如物体重量为3时,j为3,放入比较,j为4,与体积为1放入比较,在为6之前,实际上数据还可以用上一行的,但是j为6时,要比较3个,两个该物体都不放,与放一个该物体其他空间用别的物体,还有放两个,前两者通过j为3时已经比较过,这时调用比较结果,得出最后比较结果,因此完全背包j必须从1开始,数据也需覆盖,目前理解是这样。
多重背包:
number数组存放每个物体的数量
for i=1;i<=n;i++
{
if number[i]*weight[i]<=w
number[i]=number[i];
else
number[i]=w/weight[i]
}
for i=1;i<=n;i++
{
for k=1;k<=number[i];k*=2
{
for j=w;j>=1;j--
{
bag[j]=max(bag[j],bag[j-weight[i]*k]+value[j]*k);
}
}
}
注:
二分,减时间,拆分后用的是0-1背包,因此,背包的第二层循环(不算二进制拆分)循环从w开始。