有重复的背包 - 数组解决方案
Posted
技术标签:
【中文标题】有重复的背包 - 数组解决方案【英文标题】:Knapsack with repetition - array solution 【发布时间】:2015-04-24 04:28:21 【问题描述】:我正在尝试理解课堂上给我的背包算法,特别是以下伪代码。
这是我尝试编写的代码:
//Init array
var solution = [];
var items = problem.items;
var sackSize = problem.knapsack;
solution[0] = 0;
for(var k = 1; k <= sackSize; k++)
var loot = 0;
for(var i = 1; i <= items.length; i++)
if(k >= items[i].weight)
loot = Math.max(loot, items[i].value)
solution[k] = loot;
这对我来说没有意义,因为if(k >= items[i].weight)
在循环的最后一次迭代中总是给出“索引越界”错误。 items
数组从索引 0 开始,但 i
从 1 开始。为什么我们从索引 1 开始?我是否误解了变量?
我得到了:
对象问题包括背包的最大重量 (problem.knapsack) 和一系列可用项目 (problem.items)。 每个项目都是一个具有重量和价值属性的对象 (problem.items[i].weight 和problem.items[i].value)。这两个 函数应该返回一个选定项目的数组。中的项目 返回的数组也应该有 weight 和 value 属性。
【问题讨论】:
在伪代码中从1
迭代到n
而不是0
到n-1
是很常见的。仅仅因为伪代码从1
迭代到n
并不意味着你的代码也必须从1
迭代到n
,尤其是当你知道数组索引从0
开始时。
@wookie919 那么你认为解决方案不依赖于从 1 开始的它吗?
【参考方案1】:
您想查看items
数组的每个元素。第一个元素是items[0]
,最后一个元素是items[items.length-1]
。
因此,你应该换行
for (var i = 1; i <= items.length; i++)
到这里:
for (var i = 0; i < items.length; i++)
现在items[i].weight
将在最后一次迭代中有效。
那么为什么伪代码会这样说呢?
for (i = 1; i <= n; i++)
嗯,伪代码使用数学约定,其中项目从 1 到 n
编号。您的代码有不同的约定,其中项目的编号从 0
到 items.length-1
。
这不是您的代码和伪代码之间的唯一区别。例如,您写的是k >= items[i].weight
而不是k ≥ W[i]
。此外,您正在使用 var
表示法声明局部变量。那是因为您的代码是一个实际的实现。伪代码是一种数学抽象。
伪代码中的抽象思想是逐个查看项目,在数学上表示为考虑W[1]
到W[n]
。在您的代码中,第一项是items[0]
,最后一项是items[items.length-1]
。您必须相应地编写for
语句。
啊,但是背包容量呢?我们是否也必须更改该循环索引?答案是不。在这里,我们正在处理具有不同含义的不同索引。我们不是在数组中查找项目,而是创建一个新数组,我们希望使用从 0 到 sackSize
的值进行索引。 solution[k]
的值是容量为k
的背包的最佳包装。
为了清楚起见,我建议您像这样声明solution
数组:
var solution = new Array(sackSize+1);
顺便说一句,作业要求你做的比伪代码做的更多。伪代码仅计算您可以通过最佳包装获得的总值。该作业要求您返回用于最佳包装的一组物品。
【讨论】:
查看我写的代码loot = Math.max(loot, items[i].value)
,但该行的伪代码有点复杂。不知道我是否错过了那个或什么,但我应该做更复杂的吗?
是的,这是正确计算解所必需的。 loot = Math.max(loot, items[i].value + solution[k - items[i].weight]);
如果有无数个相同的对象怎么办。如何解决?
@Bear - 您可以将当前的if
语句替换为迭代变量的for
循环,比如count
,表示i
类型的项目数。只要项目符合k
(当前背包限制),就继续增加count
。整个循环看起来像这样:for (var count = 1; count * items[i].weight <= k; ++count) loot = Math.max(loot, count * items[i].value + solution[k - count * items[i].weight]);
以上是关于有重复的背包 - 数组解决方案的主要内容,如果未能解决你的问题,请参考以下文章