最大硬币分配

发布于 2024-10-16 19:33:06 字数 693 浏览 4 评论 0原文

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

给定一枚硬币系统的值为 v1,...,vn,有限数量的代币 a1,...,a n 以及我们需要支付的金额 s。 我们正在寻找一种算法来计算分区 x1,...,xn (其中 0<=xi< =ai) 与 x1*v1+x2*v2+...+xn*vn >= s 使得总和 x1+...+xn - R(r) 最大化,其中 r 是变化,即 r = x1*v1+x2*v2+...+xn*vn - s 和 R(r) 是从返回的硬币数量收银员。我们假设收银员拥有无限数量的所有硬币,并且总是归还最小数量的硬币(例如通过使用 SCHOENING 等人中解释的贪婪算法)。我们还需要确保没有金钱变化,因此最好的解决方案不是简单地提供所有资金(因为在这种情况下解决方案始终是最佳的)。

感谢您的创意投入!

Since standing at the point of sale in the supermarket yesterday, once more trying to heuristically find an optimal partition of my coins while trying to ignore the impatient and nervous queue behind me, I've been pondering about the underlying algorithmic problem:

Given a coin system with values v1,...,vn, a limited stock of coins a1,...,an and the sum s which we need to pay.
We're looking for an algorithm to calculate a partition x1,...,xn (with 0<=xi<=ai) with x1*v1+x2*v2+...+xn*vn >= s such that the sum x1+...+xn - R(r) is maximized, where r is the change, i.e. r = x1*v1+x2*v2+...+xn*vn - s and R(r) is the number of coins returned from the cashier. We assume that the cashier has an unlimited amount of all coins and always gives back the minimal number of coins (by for example using the greedy-algorithm explained in SCHOENING et al.). We also need to make sure that there's no money changing, so that the best solution is NOT to simply give all of the money (because the solution would always be optimal in that case).

Thanks for your creative input!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

混浊又暗下来 2024-10-23 19:33:06

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

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,找零的金额就越少,这就是您所追求的。

现在,您不再拥有每种硬币 i 1 个,而是拥有每种硬币 ia[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 向量应该相当容易。如果您需要更多详细信息,请告诉我。

If I understand correctly, this is basically a variant of subset sum. If we assume you have 1 of each coin (a[i] = 1 for each i), then you would solve it like this:

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

Then find the first k >= s and sum[k] is true. You can get the actual coins used by keeping track of which coin contributed to each sum[j]. The closest you can get your sum to s using your coins, the less the change will be, which is what you're after.

Now you don't have 1 of each coin i, you have a[i] of each coin i. I suggest this:

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

It should be fairly easy to get your x vector from this. Let me know if you need any more details.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文