我们有N金币和M银币。有k个项目,每个都有一些成本,一个金币和B银币,其中A或B也可以为零。
什么算法可以购买最大数量的物品?
答案 0 :(得分:4)
您描述的问题不是Knapsack problem。在这里,您只想最大化项目数量,而不是总成本。在背包问题中,你感兴趣的是最大化总成本,同时尊重麻袋的容量。换句话说,你想要抓住适合你口袋的最有价值的物品。你真的不关心它们中有多少,只是它们是最有价值的那些!
下面,我们将讨论问题的两个变种:
假设你只允许花N金币和M银币,这里有一个应该有效的算法:
1. Sort the items by cost, from cheapest to the most expensive.
2. totalCost = 0; i = 1
3. while totalCost <= goldToCost(N) + silverToCost(M) + item[i].cost
4. totalCost = totalCost + items[i].cost
5. i++
6. endWhile
7. return i
由于排序,此算法仅占用 O(nlogn)时间。
上述解决方案假设两种货币可以相互转换。该问题的另一个变体涉及正交货币,其中两种货币不能相互转换。在这种情况下,所有成本都将被指定为向量。
为了使用动态编程算法解决这个问题。我们需要询问是否展示以下两个特征:
S(M, N)
成为我们可以使用M金币和N银币购买的最大物品数量。我们可以使用递归关系推导出S(M, N)
吗?想象一下具有N行和M列的二维表。
+---+---+---+---+---+-----+---+
| | 0 | 1 | 2 | 3 | ... | N |
+---+---+---+---+---+-----+---+
| 0 | | | | | | |
| 1 | | | | | | |
| 2 | | | | | ... | |
| 3 | | | | | | |
| : | | | | | | |
| M | | | | | | |
+---+---+---+---+---+-----+---+
我们的算法基本上会填写此表。在行i
,列j
S[i, j]
中,可以使用我的金币和j银币购买最大数量的商品。
要完成该表,我们可以使用两个按字典顺序排序的数组I
和D
。在第一个,黄金作为主要的排序关键,银色seconday。在第二,银是主要的,黄金是次要的。填写第0行和第3列是直截了当的。然后我们串联遍历两个排序的数组,然后我们可以使用以下重复来完成表
S[0, 0] = 0
S[i, j] = 0 if i < 0 or j < 0
S[i, j] = max(S[i-1,j-1] + d[i-1,j-1], S[i-1,j] + d[i-1,j], S[i,j-1] + d[i,j-1])
其中d[i*,j*]
是您可以使用<i,j> - <i*, j*>
购买的其他项目数,其中<i*, j*>
是{<i-1, j-1>, <i-1, j>, <i, j-1>}
之一。换句话说,你可以用剩余的钱购买多少钱。对此进行计算的搜索涉及对两个按字典顺序排序的序列之一(I
或D
)进行二进制搜索。
此解决方案需要 O((MN + n)logn)时间来计算并使用 O(MN + n)空间。
答案 1 :(得分:4)
在这个问题中,每个项目都有二维成本。让项目i有成本c [i] = &LT; a,b>其中a是金币的成本,b是银币的成本。
这些项目现在可以部分订购,以便项目i比项目j“不是更贵”,如果
c[i] = <a, b> c[j] = <a', b'> and a <= a' AND b <= b'
请注意,这是部分订单。两个项目&lt; 1,2&gt;和&lt; 2,1&gt;在这种偏序中没有可比性;没有一个比另一个更贵。
现在很清楚,贪婪算法可以安全地购买物品,只要它们“不是更贵”,而每个其他剩余物品,但是当有多个不可比项目时可用,可能需要更多分析(例如搜索)。
例如,如果费用是
<1, 1>
<2, 1>
<1, 2>
<3, 3>
这导致了这个部分顺序:
<1, 1>
/ \
<2, 1> <1, 2>
\ /
<3, 3>
(底部最贵的物品)。贪婪算法将首先购买&lt; 1,1&gt;。之后,&lt; 2,1&gt;都是&lt; 2,1&gt;。和&lt; 1,2&gt;是可行的购买选择。如果算法选择购买&lt; 2,1&gt;,则下一个购买是&lt; 1,2&gt;。因为它现在不比所有其他剩余物品(&lt; 3,3&gt;)更昂贵。
简单的贪婪算法可能会失败。设置&lt; 2,1&gt;,&lt; 1,2&gt;,&lt; 3,0&gt;并且初始金币数量= 4,银= 2,最佳解决方案是&lt; 1,2&gt;和&lt; 3,0&gt;,但购买&lt; 2,1&gt;首先导致只能购买该商品(购买时剩下的是&lt; 2,1&gt;硬币,不允许购买剩下的两件商品)。
我会接受这个购买建立部分订单结构然后执行回溯搜索。如果时间限制不允许完全回溯,我会使用有限的回溯作为其他贪心算法的启发式算法。
答案 2 :(得分:-2)
没有“算法”。
您正在描述背包问题的一个版本,这是一个众所周知的NP完全问题。对于问题的小版本,使用小N,M和k,您只需经历所有不同的组合。对于较大的版本,没有已知的方法可以找到一个“最佳”解决方案,该解决方案需要的时间少于宇宙的生命周期才能计算出来。
最接近解决这个问题涉及一个称为线性规划的领域。这不是一件简单的事情,但如果你愿意的话,你可以去阅读它。