algorithm - 对于给定的 cent 数量,如果所有管都装有 64 但不需要填充,则最小化硬币管的数量

标签 algorithm language-agnostic

编辑:如果有人可以为著名的硬币找零问题提供一个解释性的递归答案(一个链接就可以),这将有很大帮助


对于给定的分值,如果所有硬币管都能容纳 64 个硬币,则尽量减少硬币管的数量。

每个 pipe 只能装一种硬币。

每个 pipe 不需要装满。


例如对于美国硬币,金额为 0.01 美元、0.05 美元、0.10 美元、0.25 美元、0.50 美元和 1.00 美元

6 美分可以像 6 个 1 美分硬币一样装在一个 pipe 里,

25 美分可以是装有一枚 25 分硬币的 pipe ,也可以是装有五枚 5 分硬币的 pipe 。

65 美分将作为 13 个 5c 硬币完成,因为 65 个 1c 硬币需要使用 2 个 pipe 。


我正在尝试编写一个 minecraft 插件,但我在使用该算法时遇到了很多困难。

最佳答案

查找表是一个很好的方法。

int[] Coins = new[] { 100, 50, 25, 10, 5, 1 };
int[,] Table = new int[6,6400];

/// Calculate the number of coins of each type that minimizes the number of
/// tubes used.
int[] Tubes(int cents)
{
    int[] counts = new int[Coins.Length];
    if (cents >= 6400)
    {
        counts[0] += (cents / 6400) * 64; // number of coins in filled $1-tubes
        cents %= 6400;
    }
    for (int i = 0; i < Coins.Length; i++)
    {
        int count = Table[i, cents]; // N coins in (N + 63) / 64 tubes
        counts[i] += count;
        cents -= count * Coins[i];
    }
    return cents;
}

要计算表格,您可以使用:

void CalculateTable()
{
    for (int i = Coins.Length-1; i >= 0; i--)
    {
        int coin = Coins[i];
        for (int cents = 0; cents < 6400; cents++)
        {
            if (i == Coins.Length-1)
            {
                // The 1 cent coin can't be divided further
                Table[i,cents] = cents;
            }
            else
            {
                // Find the count that minimizes the number of tubes.
                int n = cents / coin;
                int bestTubes = -1;
                int bestCount = 0;
                for (int count = cents / coin; count >= 0; count--)
                {
                    int cents1 = cents - count * coin;
                    int tubes = (count + 63) / 64;
                    // Use the algorithm from Tubes() above, to optimize the
                    // lesser coins.
                    for (int j = i+1; j < Coins.Length; j++)
                    {
                        int count1 = Table[j, cents1];
                        cents1 -= count1 * Coins[j];
                        tubes += (count1 + 63) / 64;
                    }
                    if (bestTubes == -1 || tubes < bestTubes)
                    {
                        bestTubes = tubes;
                        bestCount = count;
                    }
                }
                // Store the result
                Table[i,cents] = bestCount;
            }
        }
    }
}

CalculateTable 在几毫秒内运行,因此您不必将其存储到磁盘。

示例:

Tubes(3149)  -> [ 31,  0,  0,  0,  0, 49]
Tubes (3150)  -> [  0, 63,  0,  0,  0,  0]
Tubes (31500) -> [315,  0,  0,  0,  0,  0]

数字表示硬币的数量。 N 个硬币可以放入 (N + 63)/64 个 pipe 中。

关于algorithm - 对于给定的 cent 数量,如果所有管都装有 64 但不需要填充,则最小化硬币管的数量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12337586/

相关文章:

java - 为这个 rand 生成器建议一些更优化的解决方案

java - 对等价类的元素进行分组的数据结构

python - 根据属性将两个人匹配在一起

algorithm - 如何创建具有常量行列总和的 1's and 0' 的对称矩阵

c++ - 在类的树层次结构中访问对象时避免空指针

model-view-controller - 真实世界的MVC-处理表格

api - 在什么情况下代理会删除 HTTP 请求 header ?

algorithm - 找到一段最终周期序列

language-agnostic - 移植和迁移在编程上有区别吗?

ruby - tunnlr 等服务如何工作?