1 问题描述
在8枚外观相同的硬币中,有一枚是假币,并且已知假币与真币的重量不同,但不知道假币与真币相比较轻还是较重。可以通过一架天平来任意比较两组硬币,设计一个高效的算法来检测这枚假币。
2.1 减治法原理叙述
在说减法法原理之前,我们先来简单看看分治法原理:分治法是把一个大问题划分为若干子问题,分别求解子问题,然后再把子问题的解进行合并得到原问题的解。
而减治法同样是把大问题分解成为若干个子问题,但是这些子问题不需要分别求解,只需求解其中的一个子问题,也无需对子问题进行合并。换种说法,可以说减治法是退化的分治法。
减治法原理正式描述:减治法(reduce and conquer method)将原问题的解分解为若干个子问题,并且原问题的解与子问题的解之间存在某种确定关系,如果原问题的规模为n,则子问题的规模通常是n/2 或n-1。
2.2 8枚硬币规模解法
求解思路:
(1)首先输入8枚硬币重量,存放在一个长度为8的一维数组中。
(2)定义a,b,c,d,e,f,g,h八个变量,分别对应一枚硬币的重量。然后把这8枚硬币分成三组,分别为abc(abc = a+b+c)、def(def = d+e+f)、gh。
(3)比较adc和def的大小。如果abc = def,则假币必定是g或者h,然后把g和h分别与真币a进行比较大小,从而得到假币。如果abc > def,则g和h必定为真币,然后比较ae(ae = a+e)和bd(bd = b+d)大小(PS:此处意思为ae = abc - c并把b和e交换位置,bd = def - f并把e和b交换位置),如果ae = bd,则假币必定是c或者f,然后依次与g比较,从而得到假币;如果ae > bd,则假币必定是a或者d,然后依次与g比较,从而得到假币;如果ae < bd,则假币必定是e或者b,然后依次与g比较,从而得到假币。
(4)abc < def情况参照(3)中思想求解,最终得到假币。
具体程序流程图如图1所示:
package com.liuzhen.coin;
import java.util.*;
public class EightCoins {
public static void printFakeCoin(int [] A){
int a,b,c,d,e,f,g,h; //八枚硬币重量
a = A[0];
b = A[1];
c = A[2];
d = A[3];
e = A[4];
f = A[5];
g = A[6];
h = A[7];
int abc = a+b+c;
int def = d+e+f;
//当abc重量大于def重量时,找出其中假币,并打印输出
if(abc > def){
if(a+e > b+d){ //此时,假币必定为a或者d
if(a > g)
System.out.println("假币为第1枚硬币,较重,重量为:"+a);
else{
if(a < g)
System.out.println("假币为第1枚硬币,较轻,重量为:"+a);
else{
int test = d-g;
if(test > 0)
System.out.println("假币为第4枚硬币,较重,重量为:"+d);
else
System.out.println("假币为第4枚硬币,较轻,重量为:"+d);
}
}
}
if(a+e == b+d){ //此时,假币必定为c或者f
if(c > g)
System.out.println("假币为第3枚硬币,较重,重量为:"+c);
else{
if(c < g)
System.out.println("假币为第3枚硬币,较轻,重量为:"+c);
else{
int test = f-