- 背包容量= 2000万
- 物品数量= 500
- 每个物品的重量是介于100到2000万之间的随机数
- 每个物品的利润是介于1到10之间的随机数
请给我一个简单的解释,因为我是新手...
动态规划 (DP):
遗传算法 (GA):
爬山算法:
DP (或任何 NP 完全问题的精确算法) 通常只适用于相对较小的问题,或者找到全局最优解是最重要的事情。
有两种 DP 的方法:(有一个相当简单的优化,只需存储 2 行,我的内存使用分析建立在这种优化被使用的假设上)
Have a matrix of items x weight, with cell value being the maximum value
Matrix size = 500 x 20 000 000
Running time = O(500 * 20 000 000) = O(10 000 000 000)
Memory = max 10 * 500 -> 5 000 -> short = 2 bytes -> 2 * 20 000 000 * 2 = 80 000 000 < 80 MB
Explanation: A[i,j] below represents the best (highest) value obtainable from any subset of the elements 1 to i with weight less than or equal to j. The update rule below means - find the best value between either not including the current element (thus the weight and value stays the same) or including it (so lookup the optimal value for (the current weight minus the current item's weight) and add the value of the current item to it). Then just return the A[500, 20000000], which represents the highest value obtainable from any subset of all elements with a maximum weight of the knapsack size.
Algorithm:
A[0, 0..20000000] = 0
for i = 1:500
for x = 0:20000000
A[i, x] = max(A[i-1, x], value(i) + A[i-1, x-weight(i)])
// ignore value(i) + A[i-1, x-weight(i)] when weight(i) > x
return A[500, 20000000]
Have a matrix of items x value, with cell value being the minimum weight
Matrix size = 500 x 10*500
Running time = O(500 * 10*500) = O(2 500 000)
Memory = max 20 000 000 -> int = 4 bytes -> 2 * 500 * 4 = 4 000 < 4 KB
Explanation: A[i,j] below represents the lowest weight obtainable from any subset of the elements 1 to i with value equal to j. The update rule below means - find the best value between either not including the current element (thus the weight and value stays the same) or including it (so lookup the optimal value for (the current value minus the current item's value) and add the weight of the current item to it). The value at any cell is the exact weight of a subset to produce that value, so we need to look through all the cells A[500, x], which represents minimum weight subsets of elements for any value x.
Algorithm:
A[0, 0] = 0
A[0, 1..5000] = ∞
for i = 1:500
for x = 0:5000
A[i, x] = min(A[i-1, x], weight(i) + A[i-1, x-value(i)])
// interpret A[i-1, x-value(i)] as 0 when value(i) > x
return largest x that A[500, x] <= 20000000
所以,是的,这些复杂性基本上说明了问题,你需要等待几个小时才能得到第一种方式,但只需要几秒钟就可以得到第二种方式,而且在内存使用方面也有类似的差异(尽管80 MB仍然是微不足道的)(请注意,这远非规则,每种情况都需要进行分析)。
O(numItems * knapsackCapacity)
和空间复杂度为 O(knapsackCapacity)
的情况下运行。这意味着,对于您的需求,您将有:
20.000.000 x 500 = 10.000.000.000
次操作 - 根据您的计算机性能,可能只需要几个小时;10 x 500 = 5000
。这可以用 2 字节(一个 short 类型)表示。因此,您还需要 2 x 20.000.000 / 1024 / 1024 ~= 38 MB
的内存来存储 DP 数组。同样,需要的内存并不算太多。其他人已经提到了各自的优缺点。遗传算法会更快完成,但 DP 解决方案也应该可以在几个小时内完成,并给出精确答案。
个人而言,如果等待几个小时得到解决方案不是问题,我会选择 DP。
注意:这里是空间复杂度为 O(knapsackCapacity)
的 DP:
dp[i] = maximum profit obtainable for weight i
for i = 1 to numItems do
for j = knapsackCapacity down to items[i].weight do
dp[j] = max(dp[j], dp[j - items[i].weight] + items[i].profit)
没有“最佳”方法,每种方法都有其优缺点。
在这种情况下,权衡的是找到的解的最优性 - 遗传算法并不能保证找到最佳解决方案。
以及计算解决方案所需的时间/空间 - 使用动态规划将节省一些冗余计算,但您仍然必须至少计算所有可能的组合一次才能找到最佳解决方案(或者甚至任何解决方案)。