Ruby 背包递归算法:帮助调试
下面的背包递归定义有什么问题?我同意它写得有点古怪(更好的版本会分割VAL和权重,并在递归调用上携带索引),但我仍然有兴趣知道为什么这个版本不起作用。我开始做了一个小时,但没有用Ruby 背包递归算法:帮助调试,ruby,knapsack-problem,Ruby,Knapsack Problem,下面的背包递归定义有什么问题?我同意它写得有点古怪(更好的版本会分割VAL和权重,并在递归调用上携带索引),但我仍然有兴趣知道为什么这个版本不起作用。我开始做了一个小时,但没有用 # Knapsack def k(items, w) if w == 0 || items.size < 1 return 0 end current_item = items.shift if current_item[1] > w return k(items, w
# Knapsack
def k(items, w)
if w == 0 || items.size < 1
return 0
end
current_item = items.shift
if current_item[1] > w
return k(items, w)
end
right = current_item[0] + k(items, w - current_item[1])
left = k(items, w)
return [right, left].max
end
给我9,虽然12是一个更好的解决方案 问题是调用
#shift
正在修改同一数组,删除一个项
要调试此功能,请尝试为每个调用k
一种解决方案是替换:
current_item = items.shift
与
然后更新所有递归调用以使用剩余的\u项
作为一个例子,可以更清楚地解释为什么突变导致错误的结果,考虑第一个调用:
物品
[5,10]
将放在背包中,因此我们评估是否正确。每个递归调用都将变异项
,并删除一个条目。当您在堆栈上计算任何left
时,项
数组是空的。我实际上意识到移位会发生变化,我只是认为这不会是一个问题,考虑到所有后续调用实际上都会占用剩余的项。我猜测,为什么您的解决方案有效,是因为当堆栈调用backtrack时,它们发现items数组发生了变化。我很难理解,但我想这就是原因。n_x_l,问题是当执行right=current_item[0]+k(items,w-current_item[1])
时items
被修改,所以left=k(items,w)
不会做你想做的事。尝试将后者更改为left=k([current_time,*items],w)
,但我不建议将其作为修复方法。摆脱shift
@n\u x\l我在答案中添加了更多细节,试图帮助解释为什么突变会导致错误的结果。堆栈调用回溯它们发现items数组发生了变化-这是非常正确的。如果只是递归地向下,这可能不是问题,但是递归涉及到返回堆栈,然后再次向下(计算左
),因此后续调用需要不断移动剩余项的情况并不简单。
current_item = items.shift
current_item, *remaining_items = items