算法设计--八枚硬币问题

转自巫_1曲待续

八枚硬币问题

问题描述:

在八枚外观相同的硬币中,有一枚是假币,并且已知假币与真币的重量不同,但不知道假币与真币相比较轻还是较重。可以通过一架天平来任意比较两组硬币,设计一个高效的算法来检测出这枚假币。



解决思路:

假定输入的八枚硬币:a、b、c、d、e、f、g、h

实验解决思路:把硬币分成三组,从八枚硬币中任取六枚a、b、c、d、e、f,在天平两端各放三枚进行比较。 假设a、b、c三枚放在天平的一端,d、e、f三枚放在天平的另一端,可能出现如图所示的三种比较结果。

实验步骤:

1.      将硬币分为3组:a,b,c、d,e,f、g,h,


2.      分别取a,b,c、d,e,f 放在天平的两侧,现在假设硬币abc重于def,这说明这两组中有一组包含一枚假币,但不确定是在左侧,还是右侧。

 

 

3.      由上面的我们已经知道假币在前面两组了,那么剩下的那组的两枚硬币应该是相等的,我们取其中一枚作为考量值,这里取g硬币。取左侧的一枚硬币:a硬币,再取右侧的一枚硬币:e硬币,把ae作为新左侧的硬币组合,再取右侧的一枚硬币:d硬币+考量值:g硬币作为新右侧组合。如果出现重量不等,则可确定:这两组中的一组存在一枚假币,但具体是哪一枚还没有确定。

 

4.      我们可以通过把a、e、d分别于h比较,假如与h不一样,则这枚硬币为假币,并且可以确定这枚假币是重还是轻。整个解决思路就是这样。


5.      最后结果e与h比较,e不等于h重量,并且较轻,e为最终结果。

 



代码实现:

[cpp]  view plain copy
  1. #include<iostream>  
  2. using namespace std;  
  3.   
  4. //函数声明  
  5. void eightcoin(int arr[]);  
  6. void compare(int a, int b,int real, int index1,int index2);  
  7. void print(int jia, int zhen, int i);  
  8.   
  9. int main()  
  10. {  
  11.     int i = 0;  
  12.     int arr[8];  
  13.     //这里输入a、b、c、d、e、f、g、h的重量  
  14.     cout<<"请输入八枚硬币:"<<endl;  
  15.     for(i; i < 8; i++)  
  16.     {  
  17.         cin>>arr[i];  
  18.     }  
  19.     eightcoin(arr);  
  20.   
  21.     system("pause");  
  22.     return 0;  
  23. }  
  24. /** 
  25. *  八枚硬币问题描述: 
  26. *,有一枚是假币,并且已知假币与真币的重量不同 
  27. *,但不知道假币与真币相比较轻还是较重。可以通过一架天平来任意比较两组硬币 
  28. *,设计一个高效的算法来检测出这枚假币 
  29. * @date:2013/4/27 
  30. * @author:wwj 
  31. */  
  32. void eightcoin(int arr[])  
  33. {  
  34.     //1. 取数组中的前6个元素分为两组进行比较abc,def  
  35.     //会有a+b+c > d+e+f | a+b+c == d+e+f | a+b+c < d+e+f 三种情况  
  36.     int abc = arr[0] + arr[1] + arr[2];  
  37.     int def = arr[3] + arr[4] + arr[5];  
  38.     int a = arr[0];  
  39.     int b = arr[1];  
  40.     int c = arr[2];  
  41.     int d = arr[3];  
  42.     int e = arr[4];  
  43.     int f = arr[5];  
  44.     int g = arr[6];  
  45.     int h = arr[7];  
  46.     if(abc > def)        //6枚硬币必有一枚假币,g,h为真币  
  47.     {  
  48.         if((a + e) > (d + b))    //去掉c,f,且b,e互换后,没有引起天平变化,说明假币必然是a,d中的一个  
  49.         {  
  50.             compare(a, d, g,1,3);  
  51.               
  52.         }  
  53.         else if((a + e) == (d + b))  
  54.         {  
  55.             compare(c,f,g,2,5);  
  56.         }  
  57.         else  
  58.         {  
  59.             compare(b,e,g,1,4);  
  60.         }  
  61.     }  
  62.     else if(abc == def) //假币在g,h之中,最好状态  
  63.     {  
  64.           
  65.         if(g == a)  
  66.         {  
  67.             print(h,g,7);  
  68.         }   
  69.         else  
  70.         {  
  71.             print(g,h, 6);  
  72.         }  
  73.   
  74.     }  
  75.     else                //abc < def 这两组存在一枚假币,g,h为真币  
  76.     {  
  77.         if((a + e) > (d + b))  
  78.         {  
  79.             compare(b,e,g,1,4);  
  80.         }  
  81.         else if((a + e) == (d + b))  
  82.         {  
  83.             compare(c,f,g,2,5);  
  84.         }  
  85.         else  
  86.         {  
  87.             compare(a, d, g,1,3);  
  88.         }  
  89.     }  
  90.   
  91. }  
  92. /** 
  93. * 取出可能有一枚假币的两枚假币,作为参数a和参数b 
  94. * real表示真币的重量,index1为第一枚硬币的下标,index2为第二枚硬币的下标 
  95. */  
  96. void compare(int a, int b,int real, int index1,int index2)  
  97. {  
  98.     if(a == real)  
  99.     {  
  100.         print(b,real,index2);  
  101.     }  
  102.     else  
  103.     {  
  104.         print(a, real,index1);  
  105.     }  
  106. }  
  107.   
  108. void print(int jia, int zhen, int i)  
  109. {  
  110.     if(jia > zhen)  
  111.     {  
  112.         cout<<"位置在:"<<(i + 1)<<"是假币!"<<"且偏重!";  
  113.     }  
  114.     else {  
  115.         cout<<"位置在:"<<(i + 1)<<"是假币!"<<"且偏轻!";  
  116.     }  
  117. }  


验证结果:




  • 6
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值