标准的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会提供一个算法来填充每个单元格,但要求每一个单元格都要过于昂贵。
答案 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
的新定义。