0-1背包2行如何查找元素

时间:2018-12-07 01:59:16

标签: python algorithm knapsack-problem

上课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。

1 个答案:

答案 0 :(得分:0)

就像使用常规背包一样,您将必须在DP数组中跟踪如何到达此特定状态。因此,在您的mat表中,我们将不跟踪结果的总和,而是要跟踪构成它的元素-表中的每个条目现在都是一个具有总和和名称列表的元组。

我还自由地在代码中进行了一个关键的重构-您​​看到代码中的ifelse子句看起来有多相似吗?我们可以通过基于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是最佳值,由第一和第三元素组成。

请注意,要使用额外的[:]来制作列表的副本-列表没有被深深地复制,这会弄乱我们的解决方案,因为我们会不断重复修改同一列表。

祝你学习顺利!