背包多重约束

for*_*une 1 algorithm knapsack-problem dynamic-programming bin-packing

我有一个动态的编程问题,我花了几个小时研究无济于事.

第一部分很简单:你有一个背包物品,你必须最大化这些物品的价值,同时保持低于一定的重量.

问题的第二部分是相同的,除了现在还有一个项目限制.例如:

您可以放入包中的物品的最大价值是什么,以便在重量和物品限制的情况下最大化价值?

我不知道如何实现这个问题的第二部分,我正在寻找一般的算法.

nie*_*mmi 6

在没有项目限制的动态编程解决方案中,您有2D矩阵,其中Y轴是项目索引,X轴是权重.然后对于每个项目,您选择最大的重量对

  • 如果项目权重<=权重限制,则包括项目的权重值
  • 不包括项目的重量值

以下是Python中标准解决方案的示例:

def knapsack(n, weight, values, weights):
    dp = [[0] * (weight + 1) for _ in range(n + 1)]

    for y in range(1, n + 1):
        for x in range(weight + 1):
            if weights[y - 1] <= x:
                dp[y][x] = max(dp[y - 1][x],
                               dp[y - 1][x - weights[y - 1]] + values[y - 1])
            else:
                dp[y][x] = dp[y - 1][x]

    return dp[-1][-1]
Run Code Online (Sandbox Code Playgroud)

现在,当您添加项目限制时,您必须为每个项目选择最大值,值,三元组使用的项目数

  • 如果项目重量<=重量限制,则重量值和n项包括项目
  • 重量值和n项除外项目

为了表示项目数,您只需将第三个维度添加到先前使用的表示已使用项目数的矩阵中:

def knapsack2(n, weight, count, values, weights):
    dp = [[[0] * (weight + 1) for _ in range(n + 1)] for _ in range(count + 1)]
    for z in range(1, count + 1):
        for y in range(1, n + 1):
            for x in range(weight + 1):
                if weights[y - 1] <= x:
                    dp[z][y][x] = max(dp[z][y - 1][x],
                                      dp[z - 1][y - 1][x - weights[y - 1]] + values[y - 1])
                else:
                    dp[z][y][x] = dp[z][y - 1][x]

    return dp[-1][-1][-1]
Run Code Online (Sandbox Code Playgroud)

简单演示:

w = 5
k = 2
values = [1, 2, 3, 2, 2]
weights = [4, 5, 1, 1, 1]
n = len(values)

no_limit_fmt = 'Max value for weight limit {}, no item limit: {}'
limit_fmt = 'Max value for weight limit {}, item limit {}: {}'

print(no_limit_fmt.format(w, knapsack(n, w, values, weights)))
print(limit_fmt.format(w, k, knapsack2(n, w, k, values, weights)))
Run Code Online (Sandbox Code Playgroud)

输出:

Max value for weight limit 5, no item limit: 7
Max value for weight limit 5, item limit 2: 5
Run Code Online (Sandbox Code Playgroud)

请注意,您可以稍微优化一下有关内存消耗的示例,因为在将第z项添加到解决方案时,您只需要知道z-1项的解决方案.此外,您可以检查是否可以在开始时将z项目置于权重限制之下,如果不是相应地减少项目限制.