寻找假银币

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

  现在有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个银币是假的!

 

posted @ 2015-05-19 09:50  ~风轻云淡~  阅读(519)  评论(0编辑  收藏  举报