二进制的巧妙理解——白鼠喝酒问题


**题外话:堂弟的编程辅导班给他出的题。问题挺有趣也能很好的解释二进制的应用,结合我对于二进制的理解记录下。

一、题目

已知:有10桶酒,其中有1桶有毒,而小白鼠一旦喝了,毒性会在一周后发作。现在用小白鼠做实验,要在一周后找出那桶毒酒,请问最少需要多少只小白鼠?

二、分析

先让师爷翻译翻译:
1、限定条件为10桶中有且仅有1桶有毒,10桶酒只可能有10种状态;
(10个桶,本应有2^10共1024种状态,但是由于加了限定条件故只有10种状态,这是本问题中最容易忽略的地方)
2、老鼠可以看成二进制位,喝酒后有死(1,说明喝过毒酒)/生(0,说明没喝过毒酒)两种状态
3、也就是需要用复数只老鼠的生死状态来表示10种状态


结论
问题可以翻译成:用多少位二进制能够表示1~10?答案就是四位,也就是四只老鼠

三、方法

把桶标号为1~10,写出对应的二进制(共四位)

1 :0001
2 :0010
3 :0011
4 :0100
5 :0101
6 :0110
7 :0111
8 :1000
9 :1001
10:1010
第一只老鼠(代表第0位)喝1、3、5、7、9
第二只老鼠(代表第1位)喝2、3、6、7、10
第三只老鼠(代表第2位)喝4、5、6、7
第四只老鼠(代表第3位)喝8、9、10

最后用四只老鼠的生死状态(死为1,生为0)对应到各自的位上组成4bits二进制数,其对应的十进制数值就是有毒酒桶的编号。比如第一只和第三只老鼠死了,其他两只活着,那么就是:
0101=5(0101,代表 第四只活、第三只死、第二只活、第一只死),说明是5号桶的酒有毒(因为只有这个桶第一只和第三只都喝过,其它两只都没喝过)

四、你是不是以为这就结束了?

总体来说上面的思路是没有问题的,但仔细分析上面的二进制排列你会发现,在划分的过程中我们浪费了0000、1011、1100、1101、1110、1111,只利用上了十种,也就是说平均下去我们至少浪费的1只白鼠的价值,这不是没天理吗?
我们可以优化下,从这十桶中单拎出来一桶,这样我们重新标号0~9:
0 :0000 ----》这代表我们拎出来的这桶酒,我们叫它“鼠不喝”。
1 :0001
2 :0010
3 :0011
4 :0100
5 :0101
6 :0110
7 :0111
8 :1000
9 :1001
和上面一样:
鼠1喝:1、3、5、7、9
鼠2喝:2、3、6、7
鼠3喝:4、5、6、7
鼠4喝:8、9
如此一来,如果四鼠各自干了自己的酒后都没事,那么说明第0号桶有毒。也就是通过该变标号引入数字0,我们给了鼠子们一线生机!

既然都做到这了,那么我们能不能再把鼠子们的生存率再提一提?分析下数据可以得到一个明显而又简单的结论:
1)酒桶的标号可以随便定。
2)代表标号的四位二进制里1的数量越多,死掉的鼠子越多。
3)我们从浪费的6个二进制里取出了0000替换走了1010,同理可以用1100来替换掉原本的0111。
那么我们再次给酒桶编号:
0 :0000
1 :0001
2 :0010
3 :0011
4 :0100
5 :0101
6 :0110
12:1100
8 :1000
9 :1001
和上面一样:
鼠1喝:1、3、5、9
鼠2喝:2、3、6
鼠3喝:4、5、6、12
鼠4喝:12、8、9

有的人可能会想既然可以单拎出一桶,那么有没有可能彻底省掉一只鼠?一般情况下这是不可能的:
当鼠子们向上增加位数的时候,每增加一位都使二进制数能表示的状态数量翻倍,新鼠对于团队的价值就是其他鼠的价值之和。而所谓单拎出一桶这个动作实际上是利用0为拎出的这桶进行标号,而总的位数是没有变化的。
但我们用4位来标号10桶酒是有冗余的,如果只有2桶酒,按照第一种标号方法需要二位,按照第二种方法(利用上0)只需要一位。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值