找到最便宜子集的有效算法

时间:2015-05-28 07:30:24

标签: algorithm

主题
我们有一个项目目录[{id, prodno, qty, price}]和项目包[{id, price, items:[{prodno, qty}]}] 我们必须找到最便宜的子集 - 结果{price, [[{id, qty}]]},其中包含指定的项目 - 查询[{prodno, qty}]
示例:

items = [
  {id:1, prodno:'A', qty:1, price:1},
  {id:2, prodno:'A', qty:5, price:3},
  {id:3, prodno:'B', qty:10, price:1}
]  
bundles = [
  {id:4, price:3, items:[
    {prodno:'A', qty:2},
    {prodno:'B', qty:5}
  ]}
]  
query = [
  {prodno:'A', qty:5},
  {prodno:'B', qty:4}
]  
result = {price:4, [
  [{id:2, qty:1},{id:3, qty:1}]
]}

我们要求5xA和4xB并检索1个最便宜的子集(给出5xA和10xB)。

2 个答案:

答案 0 :(得分:1)

这实际上是对covering problem集的变体 如果我没记错的话,贪心算法可以很好地解决这些问题,但可能会有更复杂的算法做得更好。

答案 1 :(得分:0)

您可以通过在有向无环图中找到最短路径来解决此问题。问题是,图形将有一个批次的顶点。如果您不知道如何解决此类图形问题,我可以在评论中发布一些链接。

要创建图表,您需要的维度与查询中的不同prodno值一样多,在本例中为2(AB)。每个维度的整数值范围为0到qty。现在,您可以在每个位置放置一个顶点,目标是从[0,0][5,4]。顶点坐标表示prodno的数量。

要添加边缘,请使用每个项目,例如{id:1, prodno:'A', qty:1, price:1},,然后从每个顶点[i,j]添加边缘,这些顶点[i+1, j]将转到1的顶点3。边表示将项目添加到集合以获取新项目集的选项。

我不确定您希望群组如何运作,但我理解您的示例,您可以向4付费使用群组prodno A,这将增加2 * {{1和5 * prodno B到你的收藏。在这种情况下,只需将[i,j]边缘格式添加到[i+2,j+5],费用为3

另外两个细节:每个边缘都必须记住它id,因此当您找到最短路径时,您可以阅读要使用的项目或组。其次,如果边缘比最大值更远,则使其达到最大值:一旦获得所需的所有prodno数量,您就不会关心您将拥有多少。< / p>

然而,对于更大的输入,这将是非常缓慢的,因为它的复杂性与所有prodno的期望数量的乘积成比例。