有界Knapsack算法返回的几种组合

时间:2015-08-20 19:32:08

标签: algorithm optimization knapsack-problem

此任务类似于有界背包问题(BKP)。 我们有约300种不同的膳食,其参数如下: ID,价格,重要性/评级,类别

例如:

id  price  importance  type
-----------------------------
1   100     78         butter
2   50      89         milk
3   70      66         milk
4   66      50         butter

我们想要选择TOP-10最佳产品组合,但是根据具体配置,我们只想吃3种黄油,2种面包和2种牛奶。这种TOP-10组合必须具有最高的重要性。 此外,我们必须考虑可用的预算。

它与背包问题有点不同,因为我们想要TOP-10结果,而不仅仅是最好的结果。 并且同一组的每一餐/产品(例如黄油)具有不同的价格和重要性/评级。

2 个答案:

答案 0 :(得分:1)

一种可能足够的启发式方法是使用进化算法(对于背包式问题进行编程相当容易),人口相当多,让它进化一段时间,然后采取前10个解决方案

获得可证明的前十大解决方案当然会更难(从字面上看 - 显然是NP难的)。一种方法是将其解决为最优,记录解决方案,添加约束以排除该解决方案,然后解决。重复这样做,直到获得前十大解决方案。

答案 1 :(得分:1)

我认为价格是整数且相当小,你正在考虑一些学校型DP解决方案。

DP一般

在动态编程算法中,对于每个状态,我们只存储一个最佳的部分解决方案。通常我们不会在物理上存储部分解决方案:只是它的成本和一些简单的回溯信息,以便以后重建它。由于最佳子结构属性,我们不会为状态存储其他解决方案:任何成本较低的部分解决方案都会延续,这与最佳部分解决方案的相同延续更为糟糕。

为了找到 k 问题的最佳解决方案,您只需为每个DP状态存储 k 最佳部分解决方案。如果对于某些状态,根本没有 k 解决方案,则存储所有这些解决方案。为什么我们可以删除比 k 其他部分解更差的部分解决方案?因为它的任何延续都会比那些 k 更好的部分解决方案的延续更糟糕。

前进式DP中的转换照常完成。当你考虑一些状态时,你应该迭代它的所有 k 最佳部分解决方案,并尝试以各种可能的方式继续它们中的每一个(例如,是否采取新项目)。对于每个延续,请查看其状态。将延续项插入最佳部分解决方案的排序列表中。如果结果有 k + 1 部分解决方案,请删除最差的解决方案。

您肯定不希望在DP中存储部分解决方案。相反,只存储每个部分解决方案的总成本和回溯信息。回溯信息应该足以明确地确定DP中的先前部分解决方案。通过这种方式,您可以找到最佳 k 解决方案。似乎具有 k 最佳解决方案的DP解决方案需要 O(k)倍的内存和 O(k ^ 2)倍的时间(或 O(k log k))用于背包,与仅找到一个最佳解决方案相比。

特殊问题

在我看来,你应该用两级算法来解决你的问题:

  1. 在每个项目类别中运行DP以解决有界背包问题。因此,您将获得 k 该类别项目的最佳组合,每个总成本(以及有限的项目数量)。
  2. 找到在步骤1中获得的最佳解决方案组合。必须从所考虑的每个类别中获取一个解决方案。
  3. 对于单个类别,使用 W 背包大小解决DP从 N 项目列表中选择 s 项目似乎需要 O(s NW k ^ 2)时间。在步骤2中合并来自 c 类别的解决方案似乎采用 O(c W ^ 2 k ^ 2),但它可以减少到 O(c W k log(W k))如果使用平衡树进行合并。