答案 0 :(得分:1)
此解决方案有效,因为逻辑是合理的。让我们把这种逻辑写成文字:
容量C
的最大值,使用第一个n
项:
def KS(n, C):
如果我们不使用任何物品或没有容量,那么我们的值为零:
If n == 0 or C == 0:
result = 0
否则,如果第(n
个项目的重量大于此容量(C
),请使用我们可以为此容量获得的最佳结果(C
),而不用这个项目。这是Max value for capacity C, using any of the first to (n-1)th items
的解决方案(请记住,当前计算正在寻找KS(n, C)
,因此我们不允许在列表中第n
之后使用任何项目)
else if w[n] > C:
result = KS(n - 1, C)
否则,让我们决定是否应使用此项目:
else:
如果我们不使用第n
条,则与我们先前的可能性相同:Max value for capacity C, using any of the first to (n-1)th items
的解决方案:
tmp1 = KS(n - 1, C)
如果确实使用它,由于当前计算正在寻找容量C
的解决方案,因此,我们可以使用以前的{{1}中的任何一个,将当前值v[n]
添加到我们的解决方案中}项,但容量为n-1
,因此,与当前权重C - current_weight
一起,我们将展示仍保留容量w[n]
的解决方案:
C
选择较高的值:
tmp2 = v[n] + KS(n - 1, C - w[n])
返回我们当前参数的正确结果:
result = max{ tmp1, tmp2 }
递归可能有点违反直觉。调用return result
会产生大量对“较早”参数KS(n, C)
,n - 1
等的调用,并且容量较低,这使得这些调用似乎在之后发生初始通话。但是实际上n - 2
正在等待所有这些操作完成才能回答自己的计算,因此我们可以准确地说出它是在“更早的”参数调用之后发生的。当参数值重合时,它们中的许多可能会重复出现,这就是为什么对它们进行缓存以加快例程效率的原因。
将KS(n, C)
视为公式的“搜索空间”也很有用。这意味着我们实际上仅限于n, C
不同的参数组合。这就是为什么某些递归(例如背包)经常被列表为n * C
和n
上的迭代(例如嵌套C
循环)的原因。
答案 1 :(得分:0)
此方法可能会执行详尽搜索。
这是分支和边界启发法的实现,其中if-condition限制了当前分支,因为它无法进一步增长。
如果没有这种切割算法,则会为所有可能的子集(tmp1和tmp2是选择-我们是否使用当前项目)构建完整的二叉树(
答案 2 :(得分:0)
该解决方案基本上是尝试将项目n
放入(仅在仍适合的情况下)或将其丢弃,然后尽可能多地放入其余项目(递归调用)。这给出了两个值tmp1和tmp2。然后,它将使用其中的最大值。