寻找假银币

寻找假银币是一个非常有趣的智力题目,寻找假银币的大意如下:

  现在有8枚银币,其中一枚是假币。但是,从外观和做工上无法分辨哪枚是真币哪枚是假币,只知道假币的重量要比真币稍轻。则要求仅用一个天平,如何以最少的步骤寻找到假银币?

1. 寻找假银币算法

可以采用递归分治的思想来求解这个问题,操作步骤如下:

(1)首先为每个银币编号,然后可以将所有的银币等分为两份,放在天平的两边。

(2)因为假银币的分量较轻,因此天平较轻的一侧中一定包含假银币。

(3)再将较轻的一侧中的硬币等分为两份,重复上述做法。

(4)直到剩下两枚硬银币,可用天平直接找出假银币来。

这种方法在银币个数比较多时便显出了优势。照此思路编写寻找假银币问题求解的算法如下:

    static int falseCoin(int coin[],int low,int high){

        int i,sum1,sum2;

        int re=0;

        sum1=sum2=0;

        if(low+1==high){

            if(coin[low]<coin[high]){

                re=low+1;

                return re;

            }else{

                re=high+1;

                return re;

            }

        }

        //如果n是偶数

        if((high-low+1)%2==0){

            //记录前一半的重量

            for(i=low;i<low+(high-low+1)/2;i++){

                sum1+=coin[i];

            }

            //记录后一半的重量

            for(i=low+(high-low+1)/2;i<=high;i++){

                sum2+=coin[i];

            }

            if(sum1<sum2){

                re = falseCoin(coin,low,low+(high-low+1)/2-1);

            }else if(sum1>sum2){

                re = falseCoin(coin,low+(high-low+1)/2,high);

            }

        }else{        //n为奇数

            //记录前一半的重量

            for(i=low;i<low+(high-low)/2;i++){

                sum1+=coin[i];

            }

            //记录后一半的重量

            for(i=low+(high-low)/2+1;i<=high;i++){

                sum2+=coin[i];

            }

            if(sum1<sum2){

                re = falseCoin(coin,low,low+(high-low)/2-1);

            }else if(sum1>sum2){

                re = falseCoin(coin,low+(high-low)/2+1,high);

            }else{

                re=low+(high-low)/2+1;

                return re;

            }

        }

        return re;

    }

2. 寻找假银币求解完整代码

package com.cn.suanfaquti;



import java.util.Scanner;



public class FalseCoin {

    static final int MAXNUM=30;    //最大硬币数

    static int falseCoin(int coin[],int low,int high){

        int i,sum1,sum2;

        int re=0;

        sum1=sum2=0;

        if(low+1==high){

            if(coin[low]<coin[high]){

                re=low+1;

                return re;

            }else{

                re=high+1;

                return re;

            }

        }

        //如果n是偶数

        if((high-low+1)%2==0){

            //记录前一半的重量

            for(i=low;i<low+(high-low+1)/2;i++){

                sum1+=coin[i];

            }

            //记录后一半的重量

            for(i=low+(high-low+1)/2;i<=high;i++){

                sum2+=coin[i];

            }

            if(sum1<sum2){

                re = falseCoin(coin,low,low+(high-low+1)/2-1);

            }else if(sum1>sum2){

                re = falseCoin(coin,low+(high-low+1)/2,high);

            }

        }else{        //n为奇数

            //记录前一半的重量

            for(i=low;i<low+(high-low)/2;i++){

                sum1+=coin[i];

            }

            //记录后一半的重量

            for(i=low+(high-low)/2+1;i<=high;i++){

                sum2+=coin[i];

            }

            if(sum1<sum2){

                re = falseCoin(coin,low,low+(high-low)/2-1);

            }else if(sum1>sum2){

                re = falseCoin(coin,low+(high-low)/2+1,high);

            }else{

                re=low+(high-low)/2+1;

                return re;

            }

        }

        return re;

    }

    public static void main(String[] args) {

        int[] coin=new int[MAXNUM];

        int i,n,result;

        System.out.println("分治法求解假银币问题!");

        System.out.print("请输入银币总个数:");

        Scanner input = new Scanner(System.in);

        n=input.nextInt();

        System.out.print("请输入银币重量:");

        for(i=0;i<n;i++){

            coin[i]=input.nextInt();

        }

        result = falseCoin(coin,0,n-1);    //求解

        System.out.printf("在上述%d个银币中,第%d个银币是假的!",n,result);

    }



}

程序运行结果如下:

分治法求解假银币问题!

请输入银币总个数:7

请输入银币重量:2 2 1 2 2 2 2

在上述7个银币中,第3个银币是假的!

 

你可能感兴趣的:(寻找假银币)