此任务类似于有界背包问题(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结果,而不仅仅是最好的结果.
并且同一组的每餐(例如黄油)具有不同的价格和重要性/评级.
最佳答案 我认为价格是整数而且相当小,你正在考虑一些学校型DP解决方案.
DP一般
在动态编程算法中,对于每个状态,我们只存储一个最佳的部分解决方案.通常我们不会在物理上存储部分解决方案:只是它的成本和一些简单的回溯信息,以便以后重建它.由于最优的子结构属性,我们不存储状态的其他解决方案:任何具有较差成本的部分解决方案具有比最佳部分解决方案的相同延续更糟糕的延续.
为了找到问题的k个最佳解决方案,您可以简单地为每个DP状态存储k个最佳部分解决方案.如果对于某些状态,根本没有k个解决方案,则存储所有这些解决方案.为什么我们可以放弃比k其他部分解决方案更差的部分解决方案?因为它的任何延续都会比那些更好的部分解决方案的延续更糟糕.
前瞻性DP中的过渡照常完成.当你考虑一些状态时,你应该迭代它的所有k个最佳部分解决方案并尝试以各种可能的方式继续它们中的每一个(例如,不管新项目).对于每个延续,请查看其状态.将延续项插入最佳部分解决方案的排序列表中.如果结果有k 1个部分解,则丢弃最差的解.
当然,您不希望在DP中存储部分解决方案.相反,只存储每个部分解决方案的总成本和回溯信息.回溯信息应该足以明确地确定DP中的先前部分解决方案.通过这种方式,您可以找到最佳的k解决方案.与仅找到一个最佳解决方案相比,具有k个最佳解决方案的DP解决方案似乎需要O(k)倍的内存和O(k ^ 2)倍的背包时间(或O(k log k)).
特别的问题
在我看来,你应该用两级算法解决你的问题:
>在每个项目类别中运行DP以解决有界背包问题.因此,您将获得每个总成本(以及有限数量的项目)的类别项目的最佳组合.
>找到在步骤1中获得的最佳解决方案组合.必须从所考虑的每个类别中获取一个解决方案.
对于单个类别,解决DP以从具有W背包大小的N个项目的列表中选择s项目似乎需要O(s N W k ^ 2)时间.在步骤2中合并c类别的解决方案似乎需要O(c W ^ 2 k ^ 2),但如果使用平衡树进行合并,则可以将其减少到O(c W k log(W k)).