我有一个 products 列表,其中包含出售它的 shops 列表。

{
    'Book A': [ShopA, ShopB, ShopC],
    'Book B': [ShopC, ShopD],
    'Movie C': [ShopA, ShopB, ShopD, ShopE],
    ...
}

(各店价格不同)

每家商店也有运费。这是“按订单”的运输费用,与我的购物车中有多少物品无关。而且各个店铺也不同。

例如:如果我从 ShopA 购买“Book A”、从 ShopC 购买“Book B”和从 ShopA 购买“Movie C”,则结果价格为:Book A price in ShopA + Book B price in ShopC + Movie C price in ShopA + ShopC shipping cost + ShopA shipping cost
如果运输成本为零或者它是基于每个项目的并且是恒定的,那么我只会通过 price+shipping 字段对报价列表进行排序并从每个集合中获取第一个结果。

我需要购买 所有 项目 一次 并找到最低价格 结果集。

我不太擅长优化算法和动态编程,所以我需要一个解决方案,或者只是向正确的方向点头。

最佳答案

对于这么少的物品,我有一个解决方案。它是动态的。

我们将迭代处理每家商店。在每一步,我们都会存储当前最优惠的价格,我们可以用它来覆盖商品的所有子集。一开始,除了价格的 infinity 空子集外,其余都是 0 。请注意,所有子集都是 2^Num_products 计数,但在您的情况下,这些只有大约 1000。

现在我们如何处理下一个跟随商店:考虑到您覆盖了这家商店的所有可能的产品子集(我的意思是商店实际上可以提供的子集)以及您已经观察到的商店覆盖的所有其余产品,因此提高覆盖每个子集的最低成本。这一步需要 2^Num_products*2^Num_products=4^Num_products ,仍然是大约一百万,这是可以承受的。您对每家商店都这样做,最后的答案是涵盖所有元素的成本。所提出的解决方案的整个复杂度是 4^Num_products * num_shops,大约有 5000 万,这很好。

请注意,这仍然是指数级的,这并不奇怪。感谢阿米特对 NP 难的令人难以置信的证明。

编辑 在伪代码中添加对算法的进一步解释:

init:
 cost[subset] = infi
 cost[{}] = 0
for shop in shops
 new_prices = costs.dup()
 for set : subsets
   for covered_set : all_subsets(set)
     price = covered_set == {} ? 0 : delivery[shop]
     remaining = set
     for element : covered_set
       if shop do not sale element
         break for, choose next covered_set
       price += el_price[element]
       remaining.remove(element)
     price += costs[remaining]
     new_prices[set] = min(new_prices[set], price)
 costs = new_prices
return costs[all]

请注意,这里我使用集合作为索引 - 这是因为我实际上使用了子集的位掩码表示,例如 1101 是包含第一个、第二个和第四个元素的子集。因此,所有集合的迭代是 for (int i = 0; i < (1 << n); i++)

还有一件事:如果你想循环一个子集 S 的所有子集,你实际上可以比迭代初始集合的所有子集并检查该子集是否是 S 的子集更快。如果 S 也用位掩码 bit_mask 表示,则这个 for 循环完成工作: for(int i = bit_mask; i > 0; i = (i - 1) & bitmask) 。使用这种方法可以将算法的复杂性降低到 3^Num_products * num_shops 。但是,这有点难以理解,您可能需要手动编写一个示例,以确保我编写的循环实际上循环了 S 的所有子集。关于复杂性 - 请相信我。

EDIT2 编辑中断条件。还让我详细说明集合 remaining 及其计算:正如 dmzkrsk 指出的伪代码提到从集合中删除,但您实际上可以只分配 remaining = set ^ covered_set(再次位操作),以防使用位掩码来表示子集。

关于algorithm - 购物车最小化算法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8891405/

10-11 15:29