穷举-零钱换挣钱

来源:互联网 发布:2017年淘宝不好做了 编辑:程序博客网 时间:2024/05/01 06:45

【题】

21. 零钱换整钱


    小明手中有一堆硬币,小红手中有若干张10元的整钱。已知 1 角的硬币厚度为 1.8mm,5 角的硬币厚 1.5mm, 1 元的硬币为 2.0mm 。小明和小红一起玩游戏,小红拿出若干张10元的纸币,小明要将 1 角的硬币放成一摞,将 5 角的硬币硬币放成一摞,将 1 元的硬币放成一摞,如果 3 摞硬币一样高,并且金额能够正好小红要求的面值,则双方可以进行交换,否则没有办法交换。

输入: 
    小红希望交换几张10元的纸币

输出: 
    1 角的数量,5 角的数量,1元的数量

友情提示:要想办法减少穷举次数啊,否则............

 测试输入关于“测试输入”的帮助期待的输出关于“期待的输出”的帮助时间限制关于“时间限制”的帮助内存限制关于“内存限制”的帮助额外进程关于“{$a} 个额外进程”的帮助测试用例 1以文本方式显示
  1. 8↵
以文本方式显示
  1. 50,60,45↵
无限制64M0测试用例 2以文本方式显示
  1. 4↵
以文本方式显示
  1. No change.↵
无限制64M0
【思路】
     1、这题从数学的角度来看,是典型的求整数解的问题,因为硬币的个数只能是整数。如果列出方程,三个方程、三个伪未知数,必可解。如果没有整数解,则是“NO Change.”
     2、从最后提示可以看出,此题的考点是穷举。不同的穷举方法,会产生不同的速度,下面请看:
        (1)分别穷举1毛、5毛、1元硬币的个数,代码如下:

#include "stdio.h"#include "math.h"int main(){//这里变量的命名很DT,将就着看看吧int yi_jiao;//1角钱的个数int wu_jiao;//5角钱的个数int yi_yuan;//1元钱的个数int shi_yuan = 8;//10元钱的个数scanf("%d", &shi_yuan);getchar();int flag = 0;//标记变量,表示有木有整数解int total;//三种硬币的总值for (yi_jiao = 1; yi_jiao <= shi_yuan*100; yi_jiao++){for (wu_jiao = 1; wu_jiao <= shi_yuan*50; wu_jiao++){for (yi_yuan = 1; yi_yuan <= shi_yuan*10; yi_yuan++){if ( (fabs(yi_jiao*1.8 - wu_jiao*1.5) < 0.000001) && (fabs(wu_jiao*1.5 - yi_yuan * 2.0) < 0.000001)){       //判断浮点数相等时,不能直接用==,而是求差。total = yi_jiao / 10 + wu_jiao / 2 + yi_yuan;if (total == shi_yuan * 10){flag = 1;printf("%d,%d,%d\n", yi_jiao, wu_jiao, yi_yuan);}}}}}if (flag == 0){printf("No change.\n");}return 0;}



        (2)再分析一下可以发现,因为硬币的高度一样,所以可以只用一层循环就可以搞定。因为一元的面值最大,所以对一元的进行穷举会比较快一点。代码如下:
#include "stdio.h"int main(){//这里变量的命名很DT,将就着看看吧double yi_jiao;//1角钱的个数double wu_jiao;//5角钱的个数int yi_yuan;//1元钱的个数int shi_yuan;//10元钱的个数scanf("%d", &shi_yuan);getchar();int flag = 0;//标记变量,表示有木有整数解int total;    //三种硬币的总值for(yi_yuan = 1; yi_yuan <= shi_yuan*10; yi_yuan++){wu_jiao = yi_yuan * 4 / 3.0;yi_jiao = yi_yuan * 10 / 9.0;if (wu_jiao == (int)wu_jiao && yi_jiao == (int)yi_jiao)//判断硬币个数是否为整数{total = yi_jiao / 10 + wu_jiao / 2 + yi_yuan;if (total == shi_yuan * 10){flag = 1;printf("%d,%d,%d\n", (int)yi_jiao, (int)wu_jiao, yi_yuan);}}}if (flag == 0){printf("No change.\n");}return 0;}

       (3)再想想,看能不能更快一点,剔除一些不必要的或者不可能的情况。因为硬币厚度一样,所以总厚度肯定能整除18、15和20,及它们的最小公倍数的整数倍。代码如下:

#include "stdio.h"int main(){//这里变量的命名很DT,将就着看看吧int yi_jiao;//1角钱的个数int wu_jiao;//5角钱的个数int yi_yuan;//1元钱的个数int shi_yuan;//10元钱的个数scanf("%d", &shi_yuan);getchar();int flag = 0;//标记变量,表示有木有整数解int total;    //三种硬币的总值const int LCM = 180;//最小公倍数180int count;//最小公倍数180的倍数for(count = 1; count*LCM/20 <= shi_yuan*10; count++){yi_yuan = count * LCM / 20;wu_jiao = count * LCM / 15;yi_jiao = count * LCM / 18;total = yi_jiao / 10 + wu_jiao / 2 + yi_yuan;if (total == shi_yuan * 10){flag = 1;printf("%d,%d,%d\n", yi_jiao, wu_jiao, yi_yuan);}}if (flag == 0){printf("No change.\n");}return 0;}

        (4)最后一种,是简单也是最快的。从数学的角度,刚说过了,这个方程可以直接解出来。小学数学问题,这里就不赘述了。



原创粉丝点击