我正在尝试使用Scala中的递归解决背包问题,但我的要求是显示选择哪些项目保留在背包中。 availableMoney
表示背包尺寸。
我的代码如下:
def knapsack(availableMoney: Int,wt:List[Int],value :List[Int] ,n:Int) : Int= {
if(n == 0 || availableMoney == 0)
return 0
if (wt(n - 1) > availableMoney) {
return knapsack(availableMoney,wt,value, n - 1)
}
else {
var element1 = value(n-1) + knapsack(availableMoney- wt(n-1), wt, value, n-1)
var element2 = knapsack(availableMoney, wt, value, n-1)
return max(element1,element2);
}
}
如何知道选择哪些物品留在背包中?
答案 0 :(得分:2)
在您的代码中,您已经知道是否选择了当前元素。
如果您选择element1
(它高于element2
),则会选择最后一个(index = n-1)元素。从根本上说,你没有。
因此,您可以添加另一个从递归调用返回的输出参数,该参数将指示所选元素。
您需要修改所有return ...
以便处理它:
return 0
将成为return (0,[])
return knapsack(availableMoney,wt,value, n - 1)
保持原样。return max(element1,element2)
将返回(element1, list1.add(n-1))
或(element2, list2)
,具体取决于哪个更高,element
或element2
。另外,如果你想实现动态编程,这个问题讨论了如何返回元素而不仅仅是值:
How to find which elements are in the bag, using Knapsack Algorithm [and not only the bag's value]?
答案 1 :(得分:1)
请考虑接受amit的解决方案作为答案,我只想在此处补充其他解决方案。
在这个解决方案中,当背包解决方案不唯一时,我也会迎合这种情况。
正如amit指出的那样,修改代码以跟踪背包中的元素是很简单的。您的方法应返回tuple
而不是背包值,其中第一个条目是背包的“最大值”,第二个条目是背包中的元素列表列表,表示组合背包中的物品。
if
对应于递归的终止条件,背包中只有一个可能的组合 - 没有任何元素的背包。if
的条件为真,则无法选择项n - 1
,因此我们会重复使用下一个项目。n - 1
的权重小于availableMoney
,那么我们可以在结构中选择项目n - 1
(这相当于element1
),或在项目中留出n - 1
项。然后,返回的解决方案应该是两者中较好的一个,或者如果它们给出相同的值,则将它们合并在一起。以下是修改后的代码版本供您参考:
def knapsack(availableMoney: Int, wt: List[Int], value: List[Int], n: Int): (Int, List[List[Int]]) = {
if (n == 0 || availableMoney == 0)
return (0, List[List[Int]](List[Int]()))
if (wt(n - 1) > availableMoney) {
return knapsack(availableMoney, wt, value, n - 1)
} else {
val recur = knapsack(availableMoney - wt(n - 1), wt, value, n - 1)
val element1 = (recur._1 + value(n - 1), for (e <- recur._2) yield {e :+ wt(n - 1)})
val element2 = knapsack(availableMoney, wt, value, n - 1)
if (element1._1 > element2._1)
return element1
else if (element1._1 < element2._1)
return element2
else
return (element1._1, element1._2 ::: element2._2)
}
}