动态规划之找最少零钱的硬币问题

参考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;
    }
  
 
 

posted @ 2015-05-16 10:23  amberblue  阅读(624)  评论(0编辑  收藏  举报