n枚钱币中含有3枚假币(未知轻重)的假币问题

基础代码不再赘述,直接进行算法分析。

#已知当m(假币数量)大于2后,我们不再采用三分法,而是采用二分法

一.n为偶数

分析可知二分情况如下

一假币堆  二假币堆

三假币堆  无假币堆

可知此时直接二分,省去称重的一次,因为一定不会平衡

此时我们只知道两个堆总数相等,但是否仍然为偶数或者更细节不得而知所以在此讨论

(1)n%8==0

此时我们假设n=8m,划分n为m1 m2 m3 m4      m5 m6 m7 m8

首先称量m1 m2与m3 m4

平衡则为无假币堆或者二假币堆的1 1排列型,且另一堆不用秤都知道不平衡(因为一定是奇数假币堆)A类

不平衡则称量m5 m6与m7 m8,平衡则与A类相同

                                                   不平衡则说明,(1234)和(5678)组合为一假币堆和二假币堆                                                     且二假币堆为2 0排列型   B类

A类时,继续称量m1与m2,平衡则均为无假币堆 a

                                                   a类时,知道了另一堆(5678)为三假币堆,继续执行m=3算法。

                                             不平衡则均为单假币堆 b

                                                  b类时,(12)(34)(5678)均为一假币堆,执行m=1算法,得 到所有假币位置

B类时,目前已知为一假币堆和二假币堆且二假币堆为2 0排列型

可以知道两者在二分情况下都不会平衡,但是,二分后一定会形成两个无假币堆

假设情况为    无   1    无   2   数量均为n/4

此时互相称量最坏情况下要秤3次才能得到两个无假币组平衡的结果

得到平衡结果后,得到了两组平衡组,和剩下两组一假币堆和二假币堆

此时重点只在于区分一假币堆和二假币堆(其实一直都判别不了)

再次使用虚拟货币法,随便将一堆的重量*2,另一堆的重量加上已知的无假币堆

public static boolean ChengAddVSCopy(int a, int b, int c, int n, List<Coin> coins) {//a,c为两假币和无假币组的起始下标,b为一假币组的起始下标,n为同样的数量
        int sum1 = 0, sum2 = 0;
        for (int i = coins.get(a - 1).getId(), j = 0; j < n; i++, j++)
            sum1 += coins.get(i - 1).getValue();
        for (int i = coins.get(c - 1).getId(), j = 0; j < n; i++, j++)
            sum1 += coins.get(i - 1).getValue();
        for (int i = coins.get(b - 1).getId(), j = 0; j < n; i++, j++)
            sum2 += coins.get(i - 1).getValue();
        frequency++;
        sum2 = sum2 * 2;
        return sum1 == sum2;
    }

则此时形成了二假币堆和二假币堆或者四假币堆和一假币堆

称重可以进行判决,平衡则翻倍堆为一假币堆,叠加堆为二假币堆

                                不平衡则翻倍堆为二假币堆,叠加堆位一假币堆

各自执行m=2与m=1算法可以得到剩下三枚假币的位置

if (n % 8 == 0) {
                    boolean flag1 = Cheng(a, a + n / 4, n / 4, coins);
                    if (flag1) {//说明称量组为1+1或者无假币堆
                        boolean flag2 = Cheng(a, a + n / 8, n / 8, coins);
                        if (flag2) {//为无假币堆
                            ThreeHuaFen(a + n / 2, n / 2, coins);
                        } else {//1+1+1
                            OneHuaFen(a, n / 4, coins);
                            OneHuaFen(a + n / 4, n / 4, coins);
                            OneHuaFen(a + n / 2, n / 2, coins);
                        }
                    } else {
                        boolean flag11 = Cheng(a + n / 2, a + n / 4 * 3, n / 4, coins);
                        if (flag11) {//说明称量组为1+1或者无假币堆
                            boolean flag2 = Cheng(a + n / 2, a + n / 8 * 5, n / 8, coins);
                            if (flag2) {//为无假币堆
                                ThreeHuaFen(a, n / 2, coins);
                            } else {//1+1+1
                                OneHuaFen(a, n / 2, coins);
                                OneHuaFen(a + n / 2, n / 4, coins);
                                OneHuaFen(a + n / 4 * 3, n / 4, coins);
                            }
                        } else {//1+2且2为2+0,注意这里的顺序不一定,1和2谁在前谁在后不一定
                            //此时只要二分,就能得到两个无假币堆和1+2,
                            boolean flag21 = Cheng(a, a + n / 2, n / 4, coins);
                            if (flag21) {
                                boolean flag3 = ChengAddVSCopy(a + n / 4, a + n / 4 * 3, a, n / 4, coins);
                                if (flag3) {
                                    TwoHuaFen(a + n / 4, n / 4, coins);
                                    OneHuaFen(a + n / 4 * 3, n / 4, coins);
                                } else {
                                    TwoHuaFen(a + n / 4 * 3, n / 4, coins);
                                    OneHuaFen(a + n / 4, n / 4, coins);
                                }
                            } else {
                                boolean flag22 = Cheng(a, a + n / 4 * 3, n / 4, coins);
                                if (flag22) {
                                    boolean flag3 = ChengAddVSCopy(a + n / 4, a + n / 2, a, n / 4, coins);
                                    if (flag3) {
                                        TwoHuaFen(a + n / 4, n / 4, coins);
                                        OneHuaFen(a + n / 2, n / 4, coins);
                                    } else {
                                        TwoHuaFen(a + n / 2, n / 4, coins);
                                        OneHuaFen(a + n / 4, n / 4, coins);
                                    }
                                } else {
                                    boolean flag23 = Cheng(a + n / 4, a + n / 2, n / 4, coins);
                                    if (flag23) {
                                        boolean flag3 = ChengAddVSCopy(a, a + n / 4 * 3, a + n / 4, n / 4, coins);
                                        if (flag3) {
                                            TwoHuaFen(a, n / 4, coins);
                                            OneHuaFen(a + n / 4 * 3, n / 4, coins);
                                        } else {
                                            TwoHuaFen(a + n / 4 * 3, n / 4, coins);
                                            OneHuaFen(a, n / 4, coins);
                                        }
                                    } else {
                                        boolean flag3 = ChengAddVSCopy(a, a + n / 2, a + n / 4, n / 4, coins);
                                        if (flag3) {
                                            TwoHuaFen(a, n / 4, coins);
                                            OneHuaFen(a + n / 2, n / 4, coins);
                                        } else {
                                            TwoHuaFen(a + n / 2, n / 4, coins);
                                            OneHuaFen(a, n / 4, coins);
                                        }
                                    }
                                }
                            }
                        }
                    }

(2)n%4==0 

此时我们假设n=4m,划分n为m1 m2   m3 m4(m默认为奇数)

继续明确,(12)与(34)是一定不会平衡的

称量m1与m2,平衡则(12)为无假币堆或者二假币堆的1 1排列型  A

                        不平衡则二分秤另一堆(34),平衡则与上相同

                                                                           不平衡则说明组合(12)(34)为一假币堆和二                                                                               假币堆且二假币堆为2 0排列型   B

由于此时m1已经不能二分,所以无法继续用二分的方法判断,但是仍然可以解决

A情况时,从m1m2堆中拿两枚硬币(这里选择首尾),称量

1 2                    xx          xxxxx        xxx            xxx               n/2-1  n/2

A。平衡——真币+真币或者假币+假币此时需要分别取两枚硬币(继续首尾),称量
        1。平衡——真币+真币或者假币+假币此时称量两次得到的两组硬币(1与2),得到的结果
                a。平衡——一共取得了4枚真币,此时m1-1后为偶数,二分称量

                        boolean flag41 = Cheng(a+1, a + 1+(n/2-2)/4,(n/2-2)/4 , coins);

                        平衡则m1,m2均为无假币堆,m3+m4执行三假币算法

                        不平衡则m1,m2均为一假币堆,m3+m4也为一假币堆,执行算法

                b。不平衡——前后取出了2真2假币,此堆为二假币堆,先对下的大的一假币堆                                (n-4)执行m=1算法,最后得到假币情况后,再对这个4币堆进行求二假币
        2。不平衡——真币+假币,之前取出两枚假币的可能性消失了,知道了之前一定是两枚真币。此时其变为了一假币堆,所以将n/2-4枚钱币的一假币堆执行m=1算法,最后得到假币情况后再回头将这一枚假币判断。至于剩下的一假币堆则执行m=1算法
B。不平衡——真币+假币

直接提出这两枚,剩下的进行m=2算法,最后处理这两枚。

B情况时,将m1 m2幻视为m3 m4做的是一样的处理

else if (n % 4 == 0) {
                    boolean flag1 = Cheng(a, a + n / 4, n / 4, coins);
                    if (flag1) {//说明称量组为1+1或者无假币堆
                        boolean flag11 = Cheng(a, a + n / 2 - 1, 1, coins);//一半的首尾取一枚
                        if (flag11) {
                            boolean flag21 = Cheng(a + 1, a + n / 2 - 2, 1, coins);//再从首尾取一枚
                            if (flag21) {//仍然平衡
                                boolean flag31 = Cheng(a, a + 1, 1, coins);
                                if (flag31) {
                                    boolean flag41 = Cheng(a+1, a + 1+(n/2-2)/4,(n/2-2)/4 , coins);
                                    if(flag41){//左大堆整体都是无假币的
                                        ThreeHuaFen(a+n/2,n/2,coins);
                                    }else {
                                        OneHuaFen(a+2,(n/2-4)/2,coins);
                                        OneHuaFen(a+2+(n/2-4)/2,(n/2-4)/2,coins);
                                        OneHuaFen(a+n/2,n/2,coins);
                                    }
                                } else {//有一次取出了两枚假币,此时有4枚需要处理
                                    List<Coin> TemCoins = new ArrayList<>();
                                    TwoLink(a+2,a+n/2,n/2-4,n/2,coins,TemCoins);
                                    OneHuaFen(1, n - 4, TemCoins);
                                    SpecialChuLiTwoInFour(a, a + n/2 - 2, coins);//特殊的处理函数,有一次取的是两枚假币
                                }
                            } else {//取的不平衡,出现了假币,排除无假币堆情况,且已知第一次一定是2真币
                                truecoin=coins.get(a-1);
                                OneHuaFen(a + 2, n / 2 - 4, coins);
                                OneHuaFen(a + n / 2, n / 2 , coins);
                                TwoChuLiOneInTwo(a+1, a+n/2-2, coins);
                            }
                        } else {//刚开始就不平衡
                            List<Coin> TemCoins = new ArrayList<>();
                            TwoLink(a+1,a+n/2,n/2-2,n/2,coins,TemCoins);
                            TwoHuaFen(1, n - 2, TemCoins);
                            ThreeChuLiOneInTwo(a, a + n/2-1, coins);
                        }
                    } else {//换组
                        boolean flag11 = Cheng(a + n / 2, a + n / 4 * 3, n / 4, coins);
                        if (flag11) {//说明称量组为1+1或者无假币堆
                            //一半首尾取一枚
                            boolean flag21 = Cheng(a+n/2, a + n - 1, 1, coins);
                            if (flag21) {
                                boolean flag31 = Cheng(a+n/2+1, a + n - 2, 1, coins);//再取一枚
                                if(flag31){
                                    boolean flag41 = Cheng(a+n/2, a +n/2+1, 1, coins);
                                    if (flag41) {
                                        truecoin=coins.get(a+n/2);
                                        boolean flag51 = Cheng(a+n/2+1, a +n/2+1+(n/2-2)/4,(n/2-2)/4 , coins);
                                        if(flag51){//右大堆整体都是无假币的
                                            ThreeHuaFen(a,n/2,coins);
                                        }else {
                                            OneHuaFen(a,n/2,coins);
                                            OneHuaFen(a+n/2+2,(n/2-4)/2,coins);
                                            OneHuaFen(a+n/2+2+(n/2-4)/2,(n/2-4)/2,coins);
                                        }
                                    } else {//有一次取出了两枚假币,此时有4枚需要处理
                                        List<Coin> TemCoins = new ArrayList<>();
                                        TwoLink(a,a+n/2+2,n/2,n/2-4,coins,TemCoins);
                                        OneHuaFen(1, n - 4, TemCoins);
                                        SpecialChuLiTwoInFour(a+n/2, a + n - 2, coins);//特殊的处理函数,有一次取的是两枚假币
                                    }
                                }else{
                                    OneHuaFen(a, n / 2, coins);
                                    OneHuaFen(a + n / 2+2, n / 2-4 , coins);
                                    TwoChuLiOneInTwo(a+n/2+1, a + n - 2, coins);
                                }
                            } else {
                                OneHuaFen(a, n / 2, coins);
                                OneHuaFen(a + n / 2+1, n / 2-2 , coins);
                                TwoChuLiOneInTwo(a+n/2, a+n-1, coins);
                            }
                        } else {//1+2且2为2+0,注意这里的顺序不一定,1和2谁在前谁在后不一定
                            //此时只要二分,就能得到两个无假币堆和1+2,
                            //首先去找无假币堆
                            boolean flag21 = Cheng(a, a + n / 2, n / 4, coins);
                            if (flag21) {
                                boolean flag3 = ChengAddVSCopy(a + n / 4, a + n / 4 * 3, a, n / 4, coins);
                                if (flag3) {
                                    TwoHuaFen(a + n / 4, n / 4, coins);
                                    OneHuaFen(a + n / 4 * 3, n / 4, coins);
                                } else {
                                    TwoHuaFen(a + n / 4 * 3, n / 4, coins);
                                    OneHuaFen(a + n / 4, n / 4, coins);
                                }
                            } else {
                                boolean flag22 = Cheng(a, a + n / 4 * 3, n / 4, coins);
                                if (flag22) {
                                    boolean flag3 = ChengAddVSCopy(a + n / 4, a + n / 2, a, n / 4, coins);
                                    if (flag3) {
                                        TwoHuaFen(a + n / 4, n / 4, coins);
                                        OneHuaFen(a + n / 2, n / 4, coins);
                                    } else {
                                        TwoHuaFen(a + n / 2, n / 4, coins);
                                        OneHuaFen(a + n / 4, n / 4, coins);
                                    }
                                } else {
                                    boolean flag23 = Cheng(a + n / 4, a + n / 2, n / 4, coins);
                                    if (flag23) {
                                        boolean flag3 = ChengAddVSCopy(a, a + n / 4 * 3, a + n / 4, n / 4, coins);
                                        if (flag3) {
                                            TwoHuaFen(a, n / 4, coins);
                                            OneHuaFen(a + n / 4 * 3, n / 4, coins);
                                        } else {
                                            TwoHuaFen(a + n / 4 * 3, n / 4, coins);
                                            OneHuaFen(a, n / 4, coins);
                                        }
                                    } else {
                                        boolean flag3 = ChengAddVSCopy(a, a + n / 2, a + n / 4, n / 4, coins);
                                        if (flag3) {
                                            TwoHuaFen(a, n / 4, coins);
                                            OneHuaFen(a + n / 2, n / 4, coins);
                                        } else {
                                            TwoHuaFen(a + n / 2, n / 4, coins);
                                            OneHuaFen(a, n / 4, coins);
                                        }
                                    }
                                }
                            }
                        }
                    }

(3)n%2==0

此时我们假设n=2m,划分n为m1 m2(m默认为奇数)

首先首尾取一枚,称量

1  2  xxxxxxxxxxxxxxxxxxx   n-1  n

A。平衡——真币+真币或者假币+假币此时需要继续首尾,称量

        1。平衡——真币+真币或者假币+假币此时称量两次得到的两组硬币(1与2),得到的结果
                a。平衡——一共取得了4枚真币,此时放回两枚后为被4整除,

                       重新执行m=3算法

                b。不平衡——前后取出了2真2假币,此堆为二假币堆,先对下的大的一假币堆                                (n-4)执行m=1算法,最后得到假币情况后,再对这个4币堆进行求二假币
        2。不平衡——真币+假币,对剩下的执行m=2算法,最后处理剩下的一枚

B。不平衡——真币+假币

直接提出这两枚,剩下的进行m=2算法,最后处理这两枚。

 else {//其实与n本身为奇数没有区别
                    boolean flag1 = Cheng(a, a + n - 1, 1, coins);
                    if (flag1) {//首尾平衡
                        boolean flag2 = Cheng(a + 1, a + n - 2, 1, coins);
                        if (flag2) {
                            boolean flag3 = Cheng(a, a + 1, 1, coins);
                            if (flag3) {//4枚真币//放回靠近大堆的2枚,否则死循环。
                                truecoin=coins.get(a);
                                ThreeHuaFen(a + 1, n - 2, coins);
                            } else {//有一次取出了两枚假币,此时有4枚需要处理
                                OneHuaFen(a + 2, n - 4, coins);
                                SpecialChuLiTwoInFour(a, a + n - 2, coins);//特殊的处理函数,有一次取的是两枚假币
                            }
                        } else {
                            //为了让称量次数变少,我们选择将三段link起来
                            List<Coin> TemCoins = new ArrayList<>();
                            ThreeLink(a, 1, a + 2, n - 4, a + n - 1, 1, coins, TemCoins);
                            TwoHuaFen(1, n - 2, TemCoins);
                            ThreeChuLiOneInTwo(a + 1, a + n - 2, coins);
                        }
                    } else {//首尾不平衡
                        TwoHuaFen(a + 1, n - 2, coins);
                        ThreeChuLiOneInTwo(a, a + n - 1, coins);
                    }
                }

二、n为奇数

1  2  xxxxxxxxxxxxxxxxxxx   n-1  n

首先首尾取一枚,称量

A。平衡——真币+真币或者假币+假币此时需要继续首尾,称量

        1。平衡——真币+真币或者假币+假币此时称量两次得到的两组硬币(1与2),得到的结果
                a。平衡——一共取得了4枚真币,此时放回一枚后为被2整除,

                       重新执行m=3算法

                b。不平衡——前后取出了2真2假币,此堆为二假币堆,先对下的大的一假币堆                                (n-4)执行m=1算法,最后得到假币情况后,再对这个4币堆进行求二假币
        2。不平衡——真币+假币,对剩下的执行m=2算法,最后处理剩下的一枚

B。不平衡——真币+假币

直接提出这两枚,剩下的进行m=2算法,最后处理这两枚。

 else {
                boolean flag1 = Cheng(a, a + n - 1, 1, coins);
                if (flag1) {//首尾平衡
                    boolean flag2 = Cheng(a + 1, a + n - 2, 1, coins);
                    if (flag2) {
                        boolean flag3 = Cheng(a, a + 1, 1, coins);
                        if (flag3) {//4枚真币//放回靠近大堆的1枚,否则死循环。
                            truecoin=coins.get(a);
                            ThreeHuaFen(a + 1, n - 3, coins);
                        } else {//有一次取出了两枚假币,此时有4枚需要处理
                            OneHuaFen(a + 2, n - 4, coins);
                            SpecialChuLiTwoInFour(a, a + n - 2, coins);//特殊的处理函数,有一次取的是两枚假币
                        }
                    } else {
                        //为了让称量次数变少,我们选择将三段link起来
                        List<Coin> TemCoins = new ArrayList<>();
                        ThreeLink(a, 1, a + 2, n - 4, a + n - 1, 1, coins, TemCoins);
                        TwoHuaFen(1, n - 2, TemCoins);
                        ThreeChuLiOneInTwo(a + 1, a + n - 2, coins);
                    }
                } else {//首尾不平衡
                    TwoHuaFen(a + 1, n - 2, coins);
                    ThreeChuLiOneInTwo(a, a + n - 1, coins);
                }
            }

 

文件在此

通过百度网盘分享的文件:ThreeFakeCoins(1).zip
链接:https://pan.baidu.com/s/1LyuY36VbK5mB4xGJdUbkEw?pwd=2vx6 
提取码:2vx6

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值