通过动态编程解决具有多个约束的背包(0,1)

时间:2015-12-03 06:18:30

标签: c++ algorithm

假设我有一组重量为w且值为v的物体。我想最大化所选物体的值之和,而不是它们的重量总和超过最大值W.到现在为止,经典的背包问题。

现在假设每个对象都属于A,B,C等类......现在我希望我的解决方案中的对象能够尊重A,B,C等的确切数量。我问我的算法,或者返回最近的解决方案。

示例:

Object 1 : w=4 v=16 Type A
Object 2 : w=3 v=15 Type A
Object 3 : w=2 v=5  Type A
Object 4 : w=1 v=2  Type A
Object 5 : w=1 v=4  Type B
Object 6 : w=2 v=4  Type B
Object 7 : w=2 v=3  Type B
Object 8 : w=4 v=9  Type B
Object 9 : w=3 v=9  Type B
Object 10: w=1 v=2  Type B
Object 11: w=1 v=4  Type B
Object 12: w=4 v=8  Type C
Object 13: w=8 v=19 Type C
Object 14: w=1 v=2  Type C
Object 15: w=3 v=5  Type C

Desired number of objects : A=2 B=5 C=2

Set of objects solution : A{1,2},B{5,6,7,9,11},C{13,15}

我的第一种方法是考虑一个多维数组,其中第一个维度是对象的数量,第二个维度是最大的W,其他维度是每个类别所需的所需数量,并且在使用动态编程填充数组之后如果对象属于某个类别,则权重为1,否则为0。它不起作用,因为有时某些解决方案对 less 对象更好。

我的第二种方法是在一个类别中找到所需数量的对象的每个可能子集,并在将它们用作常规动态算法中的实例之后。它有效,但似乎不够优雅。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

只有两个维度的阵列是可以的。

首先,应用一个名为dp[n][m]的数组,其中第一个维度是对象的数量,第二个维度是w的总和。 dp[i][j]的值是v的最大值,其中第一个i对象的当前权重为j

我们可以得到等式:dp[i][j] = max (dp[i][j], dp[i-1][j-w] + v)其中wi-th对象的权重,vi-th对象的值。

您的回答是max (dp[n][j] | 0<=j<=W)

UPD1:

我并不关心类别,你可以为每个类别做到这一点

UPD2:

抱歉,我没有看到对象限制的数量,我们可以使用3维数组代替。只需拨打dp[n][k][m],其中k是选择对象的数量,nm就像之前一样。

公式更改为dp[i][j][k] = max (dp[i][j][k], dp[i-1][j-1][k-w] + v)

答案是max (dp[n][k][j] | 0<=j<=W),其中k是您的号码限制。