问题描述:
在超市里,最大的问题就是给钱和找钱。纸币的类型有100,50,20,10,5,1这么多的面值。为了完成一次固定数额的交易,比如你要买31元的物品,你可能给50元,这样对方需要找回19元,共需要使用7张纸币,或者你可以给51元,这样对方要找回20元,只需要三张纸币 。所以你也会希望交易所需要用到的纸币数目尽可能的少,这样大家都方便了。
输入:一个整数,表示要交易的金额。交易金额不超过10000元。
输出:最少所需要的纸币数目。
样例输入:31 20 194
样例输出:3 1 4
这题可以采用类似于贪心的解法。
1)对于大于100的部分,显然需要选取100面值的纸币。所以先计算出所需的100元纸币数,以及剩余要支付的金额。
2)对于剩下的金额,可能会在50-100,20-50,…,1-5这些区间,都是有两种不同的方案,第一种是采用比当前剩余要支付金额大的面额,另一种是选择比当前剩余要支付金额小一些的面额再加上需要支付的零钱。这里对于方案的选取,采用贪心取法,选择与当前剩余要支付的金额差距最小的面值的纸币进行支付。
3)对于剩余的金额采用上一步的方法进行纸币的选择,知道剩余金额为零为止。
比如说对于194
1)由于它大于100,所以首先需要一张100的纸币,这样还需要支付94元。
2)对于94,它可以选择50和100面值的纸币,由于它与100差距更小,所以选择100。这样的话就还有6元需要支付。
3)6元可以选择5和10的面值,这里与5比较接近,所以选择5。这时剩余金额为1。
4)最后1选择面值为1的纸币,所以剩余的为0,返回最终使用的纸币数,也就是4。
具体的代码实现如下:
const int SIZE = 6;
const int money[SIZE] = { 100, 50, 20, 10, 5, 1 };
int lessChangeGiven(int input)
{
if (input <= 0)
{
return 0;
}
int i;
int best;
int times = 0;
if (input >= 100)
{
times = input / 100;
input -= (times * 100);
}
if (input == 0)
{
return times;
}
for (i = 1; i < SIZE; ++i)
{
if (money[i] <= input && money[i - 1] > input)
{
break;
}
}
int method1 = input - money[i];
int method2 = money[i - 1] - input;
best = method1 >= method2 ? method2 : method1;
++times;
if (best != 0)
{
times += lessChangeGiven(best);
}
return times;
}