【问题标题】:0/1 Knapsack with integer values and irrational weights?0/1 具有整数值和非理性重量的背包?
【发布时间】:2015-01-14 10:48:25
【问题描述】:

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

我正在尝试解决权重不合理但值合理的问题。有人告诉我有一个O(nV) 解决方案,其中V 是所有值的总和。我想说这样的话:让m 成为n x V 数组,并让m[i, j] 成为最小可能的权重,以实现至少j 的值,项目1 到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

但这不起作用:像m[0, 100] 这样的单元格被初始化为向下传播的无意义垃圾。我不确定如何解决这个问题,也找不到任何信息。看起来this question 会提供一种算法来填充每个单元格,但是调用每个单元格的成本太高了。

【问题讨论】:

  • 这是不是一个错字,“权重是非理性的,但权重是有理的”,你能举个小例子吗?
  • 是的,我的错。我还不小心从损坏的解决方案中删除了一些代码。
  • @PM2Ring 不,目前没有,我认为我没有使用任何特定于 numpy 的东西?不过,已经晚了,我可能犯了一个错误。
  • 另外,m = [[0] * max_v] * len(weights) 可能不会做你想做的事。例如,m=[[0]*5]*3;m[1][1]=7;print(m) 打印 [[0, 7, 0, 0, 0], [0, 7, 0, 0, 0], [0, 7, 0, 0, 0]]。详情请见stackoverflow.com/q/240178/4014959
  • 一般情况下 DP——也许你见过这个? rosettacode.org/wiki/Knapsack_problem/Unbounded/…

标签: python algorithm knapsack-problem


【解决方案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的新定义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多