01背包

chuengchuenghq 2009-08-17 11:34:40
我在网上看到些资料关于O1背包的推倒:
定义函数f(i,j)为在1~i 件物品中选若干件装入限重为 j 的背包中的最大价值和, 那么根据上面关于第 i 件物品是否装入了背包的情况分析,我们得出关系式:
(1)当第I件物品要装入背包时,f(i,j) := (i-1件物品,限重为j-w[i]的最优解)+ v[i], 即: f(i,j) := f(i-1, j-w[i]) + v[i]
当然,第i件物品要装入是有条件限制的:第i 件物品重量小于等于背包限重,即 w[i] <= j
(2)当第i件物品不装入背包时,f(i,j) :=i-1件物品,限重为m的最优解,即: f(i,j) := f(i-1, j)
求得装入或者不装入第 i 件物品的限重为J的背包的最大价值,只需要比较这两种情况下谁的价值更大,更大者为当前问题的最优解。
f(i,j)=max{ f(i-1, j-w[i]) + v[i] , f(i-1, j) } 该方程递归结束的边界条件是:当j=0时,f(i,0)=0。


但是在软件设计师教程(不是最新)中关于01背包算法的源代码:

void find(int i , double tw , double tv)
{
int k;
if( tw + a[i].weight <= MAXWEIGHT) //选择I到当前方案
{
...
find( i + 1 , tw + a[i].weight , tv); // 这里tv总价值我的理解选择i时,推倒到i-1时候
//应该find( i + 1, tw+a[i].weight , tv - a[i].value)
...
}

if(tv - a[i].value > maxv)
{
...
find(i + 1 , tw , tv - a[i].value);//这里我觉得是 find(i + 1, tw, tv);
...

}


}



大家告诉我哪里错了?????
...全文
246 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
chuengchuenghq 2009-08-18
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 litaoye 的回复:]
似乎应该是

find(i+1 , tw+ a[i].weight , tv + a[i].value);



find(i+1 , tw, tv);

另外没看见LZ记录当前最大值的地方。
[/Quote]

如果tv的初值为就是所有背包的值的总和~ 书上似乎是对的~
绿色夹克衫 2009-08-18
  • 打赏
  • 举报
回复
似乎应该是

find(i+1 , tw+ a[i].weight , tv + a[i].value);



find(i+1 , tw, tv);

另外没看见LZ记录当前最大值的地方。
LeonTown 2009-08-18
  • 打赏
  • 举报
回复
先占座,
感觉第二个if的条件似乎有问题。。。
chuengchuenghq 2009-08-18
  • 打赏
  • 举报
回复
谢谢大家 晚上回家把代码贴全
fire_woods 2009-08-18
  • 打赏
  • 举报
回复
代码不全.
  • 打赏
  • 举报
回复
[Quote=引用楼主 chuengchuenghq 的回复:]
我在网上看到些资料关于O1背包的推倒: 
定义函数f(i,j)为在1~i 件物品中选若干件装入限重为 j 的背包中的最大价值和, 那么根据上面关于第 i 件物品是否装入了背包的情况分析,我们得出关系式:
      (1)当第I件物品要装入背包时,f(i,j) := (i-1件物品,限重为j-w[i]的最优解)+ v[i], 即: f(i,j) := f(i-1, j-w[i]) + v[i]
    当然,第i件物品要装入是有条件限制的:第i 件物品重量小于等于背包限重,即 w[i] <= j
    (2)当第i件物品不装入背包时,f(i,j) :=i-1件物品,限重为m的最优解,即: f(i,j) := f(i-1, j)
    求得装入或者不装入第 i 件物品的限重为J的背包的最大价值,只需要比较这两种情况下谁的价值更大,更大者为当前问题的最优解。
      f(i,j)=max{ f(i-1, j-w[i]) + v[i] , f(i-1, j) }    该方程递归结束的边界条件是:当j=0时,f(i,0)=0。


但是在软件设计师教程(不是最新)中关于01背包算法的源代码:
C/C++ code
void find(int i ,double tw ,double tv)
tw当前背包中装的重量 tv当前的价值。
{int k;
if( tw+ a[i].weight<= MAXWEIGHT)//选择I到当前方案 {
...
find( i+1 , tw+ a[i].weight , tv);// 这里tv总价值我的理解选择i时,推倒到i-1时候
//应该find( i + 1, tw+a[i].weight , tv - a[i].value) ...
//Step1.实现往里装,知道装不下为止,然后就可以看是不是取到最大值。
}
if(tv- a[i].value> maxv)
{
...
find(i+1 , tw , tv- a[i].value);//这里我觉得是 find(i + 1, tw, tv); ...
//Step2.实现回溯,就是假设不取i物体,往后再又可以接着装一些看,
}


}

大家告诉我哪里错了?????
[/Quote]
无天 2009-08-18
  • 打赏
  • 举报
回复
首先相信书本上的代码吧,既然能出版,肯定能经得起推敲的。
丈八涯 2009-08-18
  • 打赏
  • 举报
回复
01背包问题的分支限界法
2.界限函数的设定:
解空间树中第i层的每个节点都代表对物品1→i做出的特定选择.这个选择由从根节点到该节点的路径唯一确定:左分支表示装入某物品,右分支表示不装入该物品.对于第i层某个节点,设包中以装入物品重量为w,获得价值为v,则包中剩余重量W-w与剩余下的物品的最大单位重量价值Vi+1/Wi+1的积,于是得到限界函数:
Ub = v + (W-w)*(Vi+1/Wi+1)
fatiezhe 2009-08-18
  • 打赏
  • 举报
回复
先说说这个三元函数参数的意义,或者把代码贴全
也许是函数理解有差异吧
  • 打赏
  • 举报
回复
嗯,六楼和七楼都是正确的,我彻底明白了。

[Quote=引用 7 楼 chuengchuenghq 的回复:]
引用 6 楼 litaoye 的回复:
似乎应该是

find(i+1 , tw+ a[i].weight , tv + a[i].value);



find(i+1 , tw, tv);

另外没看见LZ记录当前最大值的地方。


如果tv的初值为就是所有背包的值的总和~  书上似乎是对的~
[/Quote]

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧