最大硬币分区

时间:2011-02-09 19:12:08

标签: algorithm greedy data-partitioning

自昨天站在超市的销售点以来,再一次尝试尝试忽略我身后不耐烦和紧张的队列,试图找到我的硬币的最佳分区时,我一直在思考潜在的算法问题:

鉴于硬币系统的值为v 1 ,...,v n ,有限的硬币库存a 1 ,... 。, n 以及我们需要支付的金额。 我们正在寻找一种算法来计算分区x 1 ,...,x n (0 <= x i &lt; = a i )x 1 * v 1 + x 2 * v 2 + ... + x n * v n &gt; = s使得和x 1 + ... + x n - R(r)最大化,其中r是变化,即r = x 1 * v 1 + x 2 * v 2 + ... + x n * v n - s和R(r)是从中返回的硬币数收银员。我们假设出纳员拥有无限量的所有硬币并且总是返回最小数量的硬币(例如使用SCHOENING等人中解释的贪婪算法)。我们还需要确保没有资金变化,因此最好的解决方案不是简单地提供所有资金(因为在这种情况下解决方案总是最优的)。

感谢您的创意投入!

1 个答案:

答案 0 :(得分:1)

如果我理解正确,这基本上是subset sum的变体。如果我们假设您有每个硬币中的一个(每个a[i] = 1 i),那么您可以这样解决:

sum[0] = true
for i = 1 to n do
    for j = maxSum downto v[i] do
        sum[j] |= sum[j - v[i]]

然后找到第一个k >= ssum[k]true。您可以通过跟踪每个sum[j]所贡献的硬币来获得所使用的实际硬币。最接近你可以使用你的硬币得到你的总和s,变化就越少,这就是你所追求的。

现在您没有每枚硬币中的1枚i,每枚硬币都有a[i] i。我建议这个:

sum[0] = true
for i = 1 to n do
    for j = maxSum downto v[i] do
       for k = 1 to a[i] do
           if j - k*v[i] >= 0 do
               sum[j] |= sum[j - k*v[i]] <- use coin i k times

从中获取x向量应该相当容易。如果您需要更多详细信息,请与我们联系。

相关问题