0/1背包有整数值和无理度权重?

时间:2015-01-14 10:48:25

标签: python algorithm knapsack-problem

标准的0/1背包问题适用于简单的DP解决方案:n个不同的对象具有无理值,整数权重和最大权重W,请生成{{1} }数组n x W并让m为项目1到m[i, j]和最多i的权重可实现的最大值。

我正试图解决权重不合理但价值合理的问题。我被告知有一个j解决方案,其中O(nV)是所有值的总和。我想说出这样的话:让V成为m数组,让n x V成为物品1至少m[i, j]值的最小可能权重到j。这将产生如下内容:

i

但这不起作用:像def knapsack(weights, values, max_weight): max_v = sum(values) m = [[0 for _ in range(max_v)] for _ in weights] for i in range(len(weights)): for j in range(max_v): if j < values[i]: m[i][j] = m[i - 1][j] else: m[i][j] = min(m[i - 1][j], weights[i] + m[i - 1][j - values[i]]) for val, col in reversed(enumerate(zip(*m))): wt = min(col) if wt <= max_weight: return col return 0 这样的单元格被初始化为无意义的垃圾向下传播。我不知道如何解决这个问题,我找不到任何信息。看起来this question会提供一个算法来填充每个单元格,但要求每一个单元格都要过于昂贵。

1 个答案:

答案 0 :(得分:1)

让我们将m的含义更改为确切给定值的最小权重。然后我们想要像

这样的初始化
m = [[(float('inf') if j else 0) for j in range(max_v + 1)] for _ in range(len(weights) + 1)]

我使用正无穷大作为不可行性的标记(我还修复了表大小中的两个逐个错误)。然后循环看起来像这样(未经测试)。

for i in range(len(weights)):
    for j in range(max_v + 1):
        if j >= values[i]:
            m[i + 1][j] = min(m[i][j], m[i][j - values[i]] + weights[i])
        else:
            m[i + 1][j] = m[i][j]

然后我们必须调整输出提取以反映m的新定义。