天平与假币的算法思考

题目

         有12枚硬币,其中有且只有1枚是假币,但不知道是重还是轻。现给定一架没有砝码的天平,问至少需要多少次称量才能确保找到这枚假币?

         进一步:如何证明某个方案是最少次数?

思想

         对于该问题,最简单的想法是把硬币分成2堆,天平左右各放6个,每堆6枚放到天枰上称量,这样的得到的结果一定是天枰是倾斜的。得不到任何其他信息,反而白白浪费了一次称量机会。因此第一次称量一定是选择一部分去称量,利用均分原理,天枰左边放一部分硬币,右边放一部分硬币,还剩下一部分硬币。从平均情况考虑,三部分中含有假币的概率是相等的。因此,第一次称量中,我们可以将12枚硬币分成3份,每份4枚硬币,记为甲、乙、丙

取甲、乙放到天枰上称量,一共会出现3种情况:

  • 平衡:说明甲乙中都不会含有假币,则假币一定在丙中,记丙中的4枚硬币为A、B、C、D。(依然不能将4枚硬币分成2份!无意义!!)取A、B放到天枰上称量,则又会出现三种不同情况:
    • AB平衡:AB不可能为假币,一定在C、D中。
      • 取C与A量,若平衡,说明D是假币;若不平衡,说明C是假币。
    • A重/B重:A为假或B为假。取甲中任意一枚(真币)与A称量。若平说明B为假币,且假币轻;若依然A重,说明A为假币且假币重;
  • 左倾:说明假币在甲或乙中。分别记甲中四枚硬币为ABCD,乙中四枚硬币为EFGH,丙中四枚硬币为IJKL(都是真币)。取ABE和CDI称量,则会出现
    • 若ABE与CDI平衡,则说明他们都是真币。FGH为假币且假币轻。取FG称量:
      • 若平衡,说明H为假币;
      • 否则FG中谁轻谁是假币。
    • 若左倾(即ABE重,CDI轻)。第一次称时,ABCD>EFGH。所以假币在AB中,且假币重;
      • A与I在称量一次,若平则B是假币,若A重,则A是假币。
    • 若右倾(即ABE轻,CDI重)。第一次称时,ABCD>EFGH。所以假币在CD中,且假币重;
      • C与I再称量一次,若平则D是假币,若C重,则C是假币。
  • 右倾:(与左倾情况完全对称)

    通过上面的分析可知,无论什么情况,3次称量就可以得出哪个是假币。

那理论上需要的最少次数如何证明呢?这样:    

  • 一次天枰称量能够得到左倾、右倾、平衡3种情况,如果把一次称量当做是一次编码,则它是3进制编码才能够表示;
  • 我们想要用3进制编码表示的是:12枚硬币,且假币的轻重未知。
    • 每枚硬币都可能是假币,共12种情况,假币有可能比真币轻,也有可能重,共12*2=24种情况;
    • 3n>=24 则n至少为3才可以。
  • 所以从信息论的角度讲,3次称量是最小值。

题目2

         有16枚硬币,其中有且只有1枚是假币,假币比真币轻。现给定一架没有砝码的天平,问至少需要多少次称量才能确保找到这枚假币?

         进一步:如何证明某个方案是最少次数?

思想

目前常见的是问采用分治法需要多少次,需要4次

先将16枚硬币随机分成AB两份,选轻的一边,排除8枚真币

再随机分成两份,依次类推,再称量3次,即可找出较轻的假币。

以上思路分治法类似于二分查找,但没什么技术含量。

接下来介绍更高效的方法。

将16枚硬币随机分成A,5: B,5: C,6

先称量A,B,若AB平衡,那么假币在C中,若A轻或者B轻,则假币在A或者B中

从上面的假币堆可能是6或者5个硬币中随机选4枚,放到天平两端

如果平衡,则硬币在剩余的1个中直接找到,只用了两次称量,或者在剩余的2个中

从上面两枚硬币中再称一次,找出较轻的假币即可

题目3

         有8枚硬币,其中有且只有1枚是假币,假币比真币重。现给定一架没有砝码的天平,问至少需要多少次称量才能确保找到这枚假币?2次

分为3,3,2,第一次称量若平衡在另外两枚中,再称一次即可

若不平衡,将重的那三枚分为1,1,1,随机选两个称量一次,若平衡在没称量的哪一个,否则在重的哪一个

理论下界 3的2次 > 8

编码的一些扩展:

假设我们有很多瓶无色的液体(比如瓶数大于100瓶),其中有一瓶是毒药,其它都是蒸馏水,实验的小白鼠喝了以后会在5分钟后死亡,而喝到蒸馏水的小白鼠则一切正常。现在假设只有5只小白鼠,请问一下,我们用这五只小白鼠,5分钟的时间,最多能够检测多少瓶液体的成分?

分析:

这道题的解法非常的巧妙,它使用了二进制来标注每一瓶液体。

第一瓶标号是 00001, 

第二瓶标号是 00010, 
第三瓶标号是 00011,

.....

第31瓶标号是 11111,

然后,让第一只老鼠喝下第一个位数为1的所有液体,让第二只老鼠喝下第二位为1的所有液体,。。。,让第5只老鼠喝下第五位为1的所有液体,

最后根据所有老鼠的状态从左到右,死了的小白鼠贴上标签1,没死的贴上0,最后得到一个序号,把这个序号换成10进制的数字,就是有毒的那瓶水的编号。 

比如:

第二只老鼠和第三只老鼠嗝了, 那么,很明显, 毒药的编号一定是 01100,因为如果毒药的编号是01000,那么第三只老鼠不会死,同理,如果毒药的编号是 01110,那么,应该有三只老鼠会死亡。 如果所有的老鼠都没有死亡,那么毒药一定存在于剩余的其它瓶液体里。所以,通过死亡老鼠的编号,我们可以确认毒药的编号。

          

猜你喜欢

转载自blog.csdn.net/u014028063/article/details/82388101