最少硬币找零问题-动态规划

动态规划把问题分为子为题,解决了这些子问题,再把子问题合并起来,便可以得到问题的解。在解决子问题过程中,需要把子问题的解保存起来方便后面使用。

最少硬币找零问题为:给予不同面值的硬币若干种种(每种硬币个数无限多),用若干种硬币组合为某种面额的钱,使硬币的的个数最少。

在现实生活中,我们往往使用的是贪心算法,比如找零时需要13元,我们先找10元,再找2元,再找1元。这是因为现实生活中的硬币(纸币)种类特殊。如果我们的零钱可用的有1、2、5、9、10。我们找零18元时,贪心算法的策略是:10+5+2+1,四种,但是明明可以用两个9元的啊。

所以可以使用动态规划,找零18元时,我们首先找18-1=17,18-2=15,18-5,=13,18-9,=9,18-10=8;再找17-1……。这样递归解决子问题

[cpp]  view plain copy
  1. #include<iostream>  
  2. using namespace std;  
  3. //money需要找零的钱  
  4. //coin可用的硬币  
  5. //硬币种类  
  6. void FindMin(int money,int *coin, int n)  
  7. {  
  8.     int *coinNum=new int[money+1]();//存储1...money找零最少需要的硬币的个数  
  9.     int *coinValue=new int[money+1]();//最后加入的硬币,方便后面输出是哪几个硬币  
  10.     coinNum[0]=0;  
  11.   
  12.     for(int i=1;i<=money;i++)  
  13.     {  
  14.         int minNum=i;//i面值钱,需要最少硬币个数  
  15.         int usedMoney=0;//这次找零,在原来的基础上需要的硬币  
  16.         for(int j=0;j<n;j++)  
  17.         {  
  18.             if(i>=coin[j])//找零的钱大于这个硬币的面值  
  19.             {  
  20.                 //if(coinNum[i-coin[j]]+1<=minNum)//所需硬币个数减少了  
  21.                 /* 
  22.                 上面的判断语句有问题,在更新时,需要判断i-coin[j]是否能找的开,如果找不开,就不需要更新。 
  23.                 多谢zywscq 指正 
  24.                 */  
  25.                 if(coinNum[i-coin[j]]+1<=minNum&&(i==coin[j]||coinValue[i-coin[j]]!=0))//所需硬币个数减少了  
  26.                 {  
  27.                     minNum=coinNum[i-coin[j]]+1;//更新  
  28.                     usedMoney=coin[j];//更新  
  29.                 }  
  30.             }  
  31.         }  
  32.         coinNum[i]=minNum;  
  33.         coinValue[i]=usedMoney;  
  34.     }  
  35.   
  36.     //输出结果  
  37.     if(coinValue[money]==0)  
  38.         cout<<"找不开零钱"<<endl;  
  39.     else  
  40.     {  
  41.         cout<<"需要最少硬币个数为:"<<coinNum[money]<<endl;  
  42.         cout<<"硬币分别为:";  
  43.         while(money>0)  
  44.         {  
  45.             cout<<coinValue[money]<<",";  
  46.             money-=coinValue[money];  
  47.         }  
  48.     }  
  49.     delete []coinNum;  
  50.     delete []coinValue;  
  51. }  
  52. int main()  
  53. {  
  54.     int Money=18;  
  55.     int coin[]={1,2,5,9,10};  
  56.     FindMin(Money,coin,5);  
  57.   
  58. }  
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值