动态规划之找最少零钱的硬币问题
参考http://blog.csdn.net/you12345678901234567/article/details/8130804
/* 硬币找零:动态规划算法
算法描述:当求解总面值为 i 的找零最少硬币数 coinsUsed[ i ] 时,将其分解成求解
coinsUsed[ i – cents]和一个面值为 cents 元的硬币,由于 i – cents < i , 其解
coinsUsed[ i – cents] 已经存在,如果面值为 cents 的硬币满足题意,那么最终解
coinsUsed[ i ] 则等于 coinsUsed[ i – cents] 再加上 1(即面值为 cents)的这一个硬币。
//////////////////////////////////////////////////////////////////////////////////////
特定的面币值:coins={由大到小排列的数组}
coinused=保存面币值为i的纸币找零所需的最小硬币数
money:需要找零的面币
coins ----0----1---2--3--4------------|
25 21 10 5 1
|--------------------------------
money=11
coinused
---0-1-2-3-4-5-6-7-8-9-10-11----|
0 1 2 3 4 1 2 3 4 5 1 2
|-------------------------------
coin
---0- 1-2-3-4-5-6-7-8-9-10-11---|
0 1 1 1 1 5 1 1 1 1 10 1
|-------------------------------
*/
#include<iostream>
using namespace std;
//输出每个币值对应的硬币
void Print(int *coin,int m)
{
if(m==0)return;
else
{
cout<<coin[m]<<" ";
Print(coin,m-coin[m]);
}
}
//找零函数
void Find(int money,int *coins,int n)
{
int *coinused=new int[money+1];//保存面币的最少零钱数
int *coin=new int[money+1];//保存面币的各个硬币
coin[0]=0;
coinused[0]=0;
int last=1;
for(int cents=1;cents<=money;cents++)//需要找零的面币都需从小到大来计算>>>>>动态规划的子问题的解组成问题的解
{
int mincoins=cents;//每个纸币找零时,最多情况为都是1组成>>>记录最小找零数
for(int kind=0;kind<n;kind++)//从前向后搜索最先满足条件的已知零钱。当money搜索到本身后,coinused值为1,但此时,循环并
//没有终止,会继续向下搜索,继续记录零钱数。因此需要比较已保存的跟新记录的
{
if(cents>=coins[kind])//要找零的面币大于等于给的候选零钱时,可以使用该零钱,即满足条件
{
int temp;
temp=coinused[cents-coins[kind]]+1;//分解为当前最大硬币和剩余的钱数所需的最少硬币数
if(temp<=mincoins)//当money搜索到本身后,coinused值为1,但此时,循环并
//没有终止,会继续向下搜索,继续记录零钱数。因此需要比较已保存的跟新记录的
{
mincoins=temp;
last=kind;//记录每个币值最后的一个硬币
}
}//end if
}//end kind
coinused[cents]=mincoins;
coin[cents]=coins[last];//与coinused相同,之前需要的都已记录
cout<<"此时的money=: "<<cents<<"对应的最少零钱数为:"
<<coinused[cents]
<<"所对应的应找零钱为: ";
Print(coin,cents);
cout<<endl;
}//end cents
}//end all
//主函数
int main()
{
int coins[5]={25,21,10,5,1};//从大到小排序,可以减少搜索时间
int money=11;
Find(money,coins,5);
return 0;
}