上课here
我仅使用两行就实现了工作中的0-1背包算法。
哪个输出正确的最终值。
名称包含正在使用的每个元素的ID。
def KnapSack(val, wt, n, W):
names = n
n = len(n)
mat = [[0 for i in range(W + 1)] for i in range(2)]
i = 0
while i < n:
j = 0
if i % 2 == 0:
while j < W:
j += 1
if wt[i] <= j:
mat[1][j] = max(val[i] + mat[0][j - wt[i]], mat[0][j])
else:
mat[1][j] = mat[0][j]
else:
while j < W:
j += 1
if wt[i] <= j:
mat[0][j] = max(val[i] + mat[1][j - wt[i]], mat[1][j])
else:
mat[0][j] = mat[1][j]
i += 1
if n % 2 == 0:
return mat[0][W]
else:
return mat[1][W]
基于此代码,我将如何输出用于创建正确背包值的元素?
例如,最终输出为54,我需要找到加在一起的哪些元素的值为54。
答案 0 :(得分:0)
就像使用常规背包一样,您将必须在DP
数组中跟踪如何到达此特定状态。因此,在您的mat
表中,我们将不跟踪结果的总和,而是要跟踪构成它的元素-表中的每个条目现在都是一个具有总和和名称列表的元组。
我还自由地在代码中进行了一个关键的重构-您看到代码中的if
和else
子句看起来有多相似吗?我们可以通过基于i % 2
的逻辑来团结他们-在我的代码中,这就是cur
。这使我们只能编写这种逻辑的-对于0-1背包,这是一个相当普遍的技巧。通常,应尽可能避免粘贴粘贴,因为它通常是错误的来源。没有代码,进一步的代码如下:
def KnapSack(val, wt, n, W):
names = n
n = len(n)
mat = [[(0, []) for i in range(W + 1)] for i in range(2)]
i = 0
while i < n:
j = 0
cur = i % 2
while j < W:
j += 1
if wt[i] <= j:
if val[i] + mat[cur][j - wt[i]][0] > mat[cur][j][0]:
mat[1 - cur][j] = (val[i] + mat[cur][j - wt[i]][0], mat[cur][j - wt[i]][1][:] + [names[i]])
else:
mat[1 - cur][j] = (mat[cur][j][0], mat[cur][j][1][:])
else:
mat[1 - cur][j] = (mat[cur][j][0], mat[cur][j][1][:])
i += 1
if n % 2 == 0:
return mat[0][W]
else:
return mat[1][W]
print(KnapSack([7, 8, 4], [3, 8, 6], ['apple', 'box', 'peach'], 10))
打印(11, ['apple', 'peach'])
,因为11是最佳值,由第一和第三元素组成。
请注意,要使用额外的[:]
来制作列表的副本-列表没有被深深地复制,这会弄乱我们的解决方案,因为我们会不断重复修改同一列表。
祝你学习顺利!