小白鼠试毒药问题

题目如下:

实验室里有1000个一模一样的瓶子,但是其中的一瓶有毒。可以用实验室的小白鼠来测试哪一瓶是毒药。如果小白鼠喝掉毒药的话,会在一个星期的时候死去,其他瓶子里的药水没有任何副作用。请问最少用多少只小白鼠可以在一个星期以内查出哪瓶是毒药:
    a. 9
    b. 10
    c. 32
    d. 999
    e. 以上都不对

这个题目很简单,拿来复习信息论和二进制编码的粗浅知识刚好合适。

首先呢,如果让我使用我的LabTop解题,那么简单了,用1000只小白鼠去试验,将瓶子和白鼠编号一一对应,哪只死了便是哪个瓶子里有毒啦!毕竟电脑资源很充裕,平时CPU利用率不到1%,实在是太清闲啦!在上面开辟1000个小白鼠出来还不简单!再说,这种方法虽然简单粗暴,却是最流行的用得最多的办法。不过我猜出这个题目的人是不希望看到这个答案的,因为不管是人还是小白鼠都不愿意看到小白鼠们横尸遍野的场面。记得我高中一位考上了医学院的同学说,小白鼠是很脆弱的,你拿一颗大头钉就可以把它钉到墙壁上面去。它们的腿骨轻轻一折也就断了。真是可怜啊!所以得继续分析下去。

那么让我们先看看理论上最少得用多少小白鼠好了:1000个瓶子里只有1个是有毒药的,其它的都是好的,那问题又简单了:将瓶子依次排列起来,无毒的用0表示,有毒的用1表示,一共只可能出现1000种不同的状态。这下好了,对1000求以二为底的对数,结果小于10,但是却大于9。看来b是一个很有前途的答案!

说到这里先打住,我们回过头看看用1000只小白鼠去试验的方法为什么不科学。随便从那1000个瓶子里取出一个来,问你是有毒的还是没有毒的,你说没有毒,那么恭喜你,极有可能你答对了!你犯错误的可能只有0.1% 。一只小白鼠的生死本身有两种完全独立的状态,可以表示1bit的信息;而随便拿出来一个瓶子,它极有可能是没有毒的,信息量只有对1000求以2为底的对数所得数值的千分之一bit那么大!即:ln(1000)/1000ln(2) bit。这个数很小,还不到0.01,看来用一只小白鼠去对付它实在太浪费了!

也许上一段文字里面有一些你不明白的东西,其中最不明白的就是信息量怎么是那样计算的。我知道你没有学过这东西所以原谅你,但是请你相信我说的是大致正确的,并且我也不会欺骗你。小事情嘛,干吗骗人呢!要骗就在大事情上骗。其实这个算法最初是香农那家伙说的,有错误你去找他好了。

剩下的,我们最关心的是用10只小白鼠能不能找出那个有毒的瓶子来,或者怎么才能找出来。答案是能够找出来的!用二进制编码的办法。我先说两句这个编码问题。我们小学的时候数数,从1数到9,再往下数,便是一个突破。进位了!二进制里面,你数到1,再往下数,困难了,因为里面只有0和1,连2都没有。麻烦了,到这里就得进位。好了,我们来数一数:0,1,10,11,100,101,110,111,1000,……看明白了吗?这样数下去,数到1111111111,10位,再加1就又要进位了就大于10位了,我们的小白鼠就不够用了。其实已经够了,你回头看看,我们从0到1111111111已经数了1024个数字。对付1000个瓶子还是够了的。

现在开始解题!把上面数过的数字,长度短于10的,前面全都加上0补够10位数字。比如1101就变成了0000001101。不过它只有1+4+8=13那么大,远远没有1000大呢!哪个数字对应十进制里面的1000呢?应该是1111111111(1023)-10000(16)-100(4)-10(2)-1(1)=1111101000(1000),这个就是十进制里面的1000。让瓶子和小白鼠都排成一列,站好了不准动,对瓶子从1到1000编号,然后把号码转化成10位长的二进制串,刚好和10只小白鼠一位对一位。一个瓶子里的二进制编号有哪几位是1,就让那些小白鼠喝下去其中的一点儿东西好了。将来那些喝了的小白鼠刚好都死了而没喝它的一只都没有死,我们就指定它有毒好啦!

如此简单的一个问题被我说到了这个地步,不禁心中大乐,哈哈哈哈,我也会瞎扯啦!不过问题还没有完全搞定。如果告诉你有1024个瓶子,用10只小白鼠能否测出来呢?你也看到了,1111111111才有1023那么大,不到1024。其实是可以的,因为我们对瓶子是从1开始编号的,而留下了0没有使用。从0到1023可是1024个数字。

那么,留一个家庭作业,呵呵:如果题目给的是1024个瓶子里面最多有一个瓶子有毒,还能够用10只小白鼠检测出来吗?这好像跟正零与负零有点儿关系。

时间: 2024-10-10 09:33:16

小白鼠试毒药问题的相关文章

小白鼠试毒药,最少需要多少即可试出结果

有 1000  桶酒,其中 1  桶有毒.而一旦吃了,毒性会在 1  周后发作.现在我们用小老鼠做 实验,要在 1  周内找出那桶毒酒,问最少需要多少老鼠. 一只老鼠喝酒后又两种状态:死(0)和活(1). 所以10只老鼠就能表示2的10次方个状态(即1024个).2^0表示2的零次方.2^8表示2的8次方. 设有10只老鼠编号分别为2^0,2^1, 2^2, 2^3, 2^4, 2^5, 2^6, 2^7, 2^8, 2^9.有1000桶酒编号为1,2,3....一直到 1000. 任何一桶酒的

关于数字的智力题-小白鼠与毒药

题目: 有1000瓶药物,但是其中有一瓶是有毒的,小白鼠吃了一个星期以后就会死掉!请问,在一个星期内找出有毒的药物,最少需要多少只小白鼠? 解答: 用二进制的思路去思考,1000瓶药代表了1000种状态,那么1000用二进制表示可以用一个10位的二进制数就可以全部表示出来,考虑用十只白鼠来试验,用0和1代表它们最终的状态即死亡或活着,初始状态十只白鼠表示为0000000000. 关于数字的智力题-小白鼠与毒药,布布扣,bubuko.com

用小白鼠喝毒药

题设:有N瓶水,其中有一瓶水有剧毒,如果小白鼠喝了会在24小时的时候死亡. 问:用多少只小白鼠能够检测出哪瓶水有剧毒? 要求:用的小白鼠数量少并且用时要短,并给出合理的过程与结论. 我的解题思路如下: 这是一个二进制开关(0/1)问题,类比于海明码校验算法,将药水进行二进制编号(0000000,0000001,0000010,0000011...),算出至少多少位二进制能够将所有的小白鼠进行完全编号: 然后根据二进制的位数选取小白鼠,将小白鼠对应于相应二进制位,之后去依次遍历不同小白鼠的相同位,

我是一只小白鼠

我是一只小白鼠,我可能很胆小.因为我害怕,我怕自己不够好.我怕被别人比下去.我怕我会落后.我怕学历不如别人.我怕我没有别人过得好... 所以我一直在努力,一直像一只小白鼠一样,不断试验着.我不会说:是被别人不断做试验,我想说:我是我的小白鼠,我是自己不断的试验.我在尝试着,尝试着去改变我的生活. 2010年我初中毕业,现在2016年了.偶尔会回想过去和现在,发现自己真的懂事了不少,对于我而言,三观早改了.很多时候我都感觉,我像是成功了一样的幸福感和幸运感.我今年22岁,我所指的成功,并非金钱或者

2943:小白鼠排队-poj

2943:小白鼠排队 总时间限制:  1000ms 内存限制:  65536kB 描述 N只小白鼠(1 < N < 100),每只鼠头上戴着一顶有颜色的帽子.现在称出每只白鼠的重量,要求按照白鼠重量从大到小的顺序输出它们头上帽子的颜色.帽子的颜色用“red”,“blue”等字符串来表示.不同的小白鼠可以戴相同颜色的帽子.白鼠的重量用整数表示. 输入 输入第一行为一个整数N,表示小白鼠的数目.下面有N行,每行是一只白鼠的信息.第一个为不大于1000的正整数,表示白鼠的重量,:第二个为字符串,表示

题目1110:小白鼠排队 Java

题目描述: N只小白鼠(1 <= N <= 100),每只鼠头上戴着一顶有颜色的帽子.现在称出每只白鼠的重量,要求按照白鼠重量从大到小的顺序输出它们头上帽子的颜色.帽子的颜色用"red","blue"等字符串来表示.不同的小白鼠可以戴相同颜色的帽子.白鼠的重量用整数表示. 输入: 多案例输入,每个案例的输入第一行为一个整数N,表示小白鼠的数目. 下面有N行,每行是一只白鼠的信息.第一个为不大于100的正整数,表示白鼠的重量,:第二个为字符串,表示白鼠的帽

1110.小白鼠排队

题目描述: N只小白鼠(1 <= N <= 100),每只鼠头上戴着一顶有颜色的帽子.现在称出每只白鼠的重量,要求按照白鼠重量从大到小的顺序输出它们头上帽子的颜色.帽子的颜色用"red","blue"等字符串来表示.不同的小白鼠可以戴相同颜色的帽子.白鼠的重量用整数表示. 输入: 多案例输入,每个案例的输入第一行为一个整数N,表示小白鼠的数目. 下面有N行,每行是一只白鼠的信息.第一个为不大于100的正整数,表示白鼠的重量,:第二个为字符串,表示白鼠的帽

小白鼠排队

题目描述 N只小白鼠(1 <= N <= 100),每只鼠头上戴着一顶有颜色的帽子.现在称出每只白鼠的重量,要求按照白鼠重量从大到小的顺序输出它们头上帽子的颜色.帽子的颜色用"red","blue"等字符串来表示.不同的小白鼠可以戴相同颜色的帽子.白鼠的重量用整数表示. 输入描述: 多案例输入,每个案例的输入第一行为一个整数N,表示小白鼠的数目. 下面有N行,每行是一只白鼠的信息.第一个为不大于100的正整数,表示白鼠的重量,:第二个为字符串,表示白鼠的

IT小白鼠第二天

今天说说感受吧 已经来了快一周了  实在是蒙圈的厉害  以前学习俄语的  英语一点都不懂 要老命了 好了不说了 下面给大家分享下 今天讲解的各大知识点 循环 while 条件: 代码块(循环体) break 彻底停止当前本层循环 continue 停止当前本次循环. 继续执行下一次循环 else: # 当条件为假的时候会执行else 代码块 2. 格式化输出 %s 占位字符串 用这个 %d 占位数字 3. 运算符(难点) and 并且. 左右两端同时为真. 结果才能是真 or 或者. 左右两端有