查找表是一个好方法。
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 个管子中。