硬币找钱问题2

  //参考:http://www.cppblog.com/cuijiaxing/archive/2012/04/15/171448.aspx

  #include <iostream>
  #include <fstream>
  using namespace std;
  ifstream ifs;

  int coins[6];//各面值硬币数
  int count = 0;//需要的最少硬币数
  int cost, c[6]={5, 10, 20, 50, 100, 200};//需支付数和硬币面值,以分计算

  void getData()  //读入数据
  {
      int flag = 0;
      cout << "                        5\t10\t20\t50\t100\t200\n";
      cout << "输入各种面值的硬币个数:";
      for(int i=0; i<6; i++)
      {
         ifs >> coins[i];   
         cout << coins[i] << "\t";
      }

      double costt;
      cout << "\n输入付款金额:";
      ifs >> costt;
      cost = (int)(costt*100);//将输入的钱转为分
      cout << cost << endl;
  }

  int contains(int a) //如果a恰好等于某一硬币面值,返回该硬币面值下标
  {

     for(int i=0;i<6;i++)
      {
          if(c[i]==a && coins[i]>0)
              return i;
      }
      return -1;
  }

  int getBackMin(int k) //返回找的钱数为k,需要最少的硬币数
  {
      int count = 0;
      for(int i = 5;i >=0;--i)
      {
          count += k /c[i];
          k = k % c[i];
      }
      return count;
  }

  //检查一个数的后面是否还有硬币,如果没有了,或者余下的硬币的和小于要找的值。那么就只能用当前硬币来计算了
  //co 为要找的钱,index为当前硬币下标
  int checkLast(int index,int co)
  {
      int sum = 0;
      for(int i =index-1;i >=0;--i )
      {
          sum += c[i] * coins[i];  //余下的硬币
      }
      if(co <= sum) //余下的硬币的和大于要找的硬币
          return 1;
      else
          return 0;
  }

  void getMinCount()
  {
      for(int i=5; i>=0; i--)  //先找面值较大的硬币
      {
          if(coins[i]>0)  //如果硬币数量不为0,则可以用此面值硬币
          {    
              int *cc = new int[i+1];
              cc[0]=0;
              for(int k=1; k<=i; k++)
              {
                  cc[k]=c[k-1]; //相当于将c[0,i-1]复制到cc[1,i]
              }
              for(int j=0; j<=i; j++)  
              {
                  if(cost >= (c[i]-cc[j]))  //如果要找的钱数>=(当前硬币面值-(比当前硬币面值小的硬币||0)),即当前硬币面值可用
                  {                         //比如要找0.55元,2元数量为0,不可用,考察1元,1元-5角=5角<0.55元,1元可用
                      if(coins[i] >= cost/(c[i]-cc[j])) //如果已有硬币的数量>=?
                      {
                            count += cost/(c[i]-cc[j])+1;  //总的要找的钱数+=?+1

                            if(contains(c[i]-cc[j])!=-1) //如果当前硬币面值-比它小的某一硬币面值恰好等于另外某一硬币面值
                            {
                                count--;  //要找的总硬币数-1   
                                coins[contains(c[i]-cc[j])] -= cost/(c[i]-cc[j]); //另外某一硬币数量 -= ?
                                cout << " " << cc[j];
                            }
                            else  //如果当前硬币面值-比它小的某一硬币面值不等于另外某一硬币面值
                            {
                                cout << " " << c[i];
                                cout << " " << cc[j];
                                coins[i] -= cost/(c[i]-cc[j]); 
                            }
                            cost = cost % (c[i]-cc[j]);    //剩余要找的钱数
                            if(contains(c[i]) == -1)
                                break;
                      }
                      else  //如果已有硬币的数量<?
                      {
                          cout << " " << c[i];
                          count += coins[i];  //总的要找的钱数 += 当前硬币的数量
                          cost = cost - c[i]*coins[i];  //要找的钱数-已找的钱数
                          coins[i]=0;   //当前硬币数量用光
                      } 
                 }
             }
             //剩下的钱不够支付了
             if(!checkLast(i,cost))
             {
                 //检查是否可以用当前的币值来支付
                 int hasLest = cost / c[i] + 1;
                 if(hasLest <= coins[i])
                 {
                     count += hasLest;
                     count += getBackMin(c[i] * hasLest - cost);
                     cost = 0;
                     break;                    
                 }
                 else
                     break; 
             }
         }

     }

     if(count==0 || cost!=0)
     {
         //cout << "impossible" << endl;
     }
     else
     {
         cout << "\n最少的硬币数为:" << count << endl;
     }

 }


 int main()
 {
     ifs.open("硬币找钱.txt");
     while(!ifs.eof())
     {
         count=0;
         getData();
         cout << "所用到的硬币有:\n";
         getMinCount();
     }
     ifs.close();
     return 0;
 }

这里写图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值