找零钱问题
问题描述
给定需要找零的金额,零钱的种类的个数,零钱的数值,输出当找零需要的硬币的个数最少时的组合。
样例输入
18
4
1 5 9 10
样例输出
9 9
程序
#include<iostream>
usingnamespace std;
int n; //用来找零的硬币的个数
int money; //需要找零的钱的值
int* coin; //用来找零的硬币
//找零
void Findcharge()
{
int* coinNum = new int[money+1]; //找零需要硬币个数的最小值
int* coinlast = new int[money+1]; //找数值为数组下标的零钱的最后一个硬币
//初始化
coinNum[0]= 0;
coinlast[0]= 0;
for(int i = 1; i <=money; i++)
{
int MinNum = i; //找零数值为i的金额需要硬币个数的最小值
int usedmoney = 0; //找零数值为i的金额还需要再加的硬币的个数 比如找零5:找零4时需要一个硬币,在有1元硬币的情况下,找零5就需要找零4的基础上再加一个1元硬币
for(int j = 0; j < n; j++)
{
if(i >= coin[j])
{
if(coinNum[i -coin[j]] + 1 < MinNum && (coinNum[i - coin[j]] != 0 || i - coin[j]== 0)) //除了k=0以外,coinNum[k] == 0表示k找不开
{
MinNum= coinNum[i - coin[j]] + 1;
coinlast[i]= coin[j];
usedmoney= 1;
}
}
}
if(usedmoney == 0) //找不开
{
coinNum[i]= 0;
coinlast[i]= 0;
}
else
coinNum[i]= MinNum;
}
if(coinNum[money] ==0)
cout<<"找不开"<< endl;
else
{
while(money > 0)
{
cout<< coinlast[money] <<' ';
money-= coinlast[money];
}
cout<< endl;
}
}
int main()
{
cin>> money >> n; //输入要找零的金额和拥有的零钱的种类的个数
coin= new int[n];
for(int i = 0; i < n; i++) //输入拥有的零钱的金额
cin>> coin[i];
Findcharge();
return 0;
}
解题思路
当找零的金额为x时可以将问题化为:x = (x – a) + a,a表示最后用到的硬币的金额,那么找零的金额为x所需要用到的硬币的总数就等于找零金额为(x – a)用到的硬币的个数加一,当用到的硬币的总数最小时,就能得到最后用到的硬币的金额(即a的值),再将a的值存起来最后用于输出找零的组合。
解释程序中的变量
*usedmoney:判断当前的金额能否找开(除金额等于0以外当usedmoney等于0时表示找不开,等于1表示找得开)
*除0外当cionNum[i] == 0时表示该金额的值找不开