小狗喝水(好玩的题目^_^)

原创 2007年10月04日 13:28:00
有1000瓶水,其中有一瓶有剧毒(假设哪怕一个毒药分子在里面也能致命),现在给你10只小狗在24小时内通过小狗试药的方式鉴定出来哪瓶药有毒。
  情况1:假设小狗服药后2小时内即可判断是否中毒,鉴别方案有哪些?
  情况2:假设小狗服药之后20小时才能判断是否中毒,鉴别方案又是什么?
又是一道智力型题目,很具有挑战性,也蛮好玩的,喜欢做这个样子的题目,有挑战性,还能够做的

让人高兴,哈哈
想自己做的就先别看下面的分析了,实在忍不住的也没有办法,想看就看吧,嘿嘿

 

下面先看看一个网友的分析:
  前天水母十大的一个帖子,挺有意思的,也算是温习一下上学期学的算法吧。其实算法课上倒是讲过类似的题目,是摔瓶实验,意思差不多,用二分法来做。同样,这个问题首先想到的就是二分法,2^10=1024>1000,实验小狗数目刚好够用,具体方案:先将1000瓶水均分成500和500两组,让1号小狗把其中一组的500瓶水都尝一下,2小时后,若该小狗死亡则说明毒水在这500瓶中,否则在另外500瓶中。将确认包含毒水的那组500瓶再均分两组,每组250瓶,让2号小狗把其中的一组的所有水都try一下,2小时后检查该小狗的身体状况。。。以此类推,每次操作都把问题规模缩小一半,所以叫二分。

    这个算法比较好理解,即使没学过相关课程的人,也能大致知道一二。不过对于情况2,虽然二分法依然可行,但作为一道题目,肯定不会让你拿一个办法对付两种情况。这两种情况的区别就在于毒药生效的时间,二分法的喂药量是最小的,但是每喂一轮就要等待毒药发作,2小时还能忍,20小时就不能忍了(小狗说:我被你们丫的拿来吃毒药,我还不能忍呢)。

    既然考虑到时间复杂度问题,最理想的情况就是同时把1000瓶水给喂下去,问题就在于如何区分。版上牛人给出的办法是用2进制的思想,把1000瓶水编号,从1、10、11、100……一直到1111101000(1000的二进制表示,正好10位),然后10条狗依次排开,分别对应从高到低10个数位,喂水的规则是:水瓶的二进制编号中有"1”的就喂给该数位对应的那条小狗,比如3号瓶二进制是11,就喂给最右边两条小狗。水都喂完了,等20小时,看看哪几条狗死了,活着的狗对应数位写0,死了的

狗对应数位写1,得到一个二进制数,那么这个二进制数对应的那瓶水有毒。

    至于这个算法的证明,大概的思路如下:有毒的水,喂食的那几条小狗肯定都会死,剩下的都不会死,只需要说明唯一性就可以了。10条小狗死亡情况的可能性,正好是2^10=1024,跟水瓶一一对应还是没问题的。

    可怜的小狗,你死得好冤哪。从人道主义角度来说,还是第一种办法好,运气好的话10条小狗都不会死。第二种办法固然是节省时间,但是碰上111111111这种的,一下子得死9条狗,太残忍了--
下面我来说两句,不能都copy人家的吧,嘿嘿
到这里大家都明白了吧?
其实这个二进制编码的方法跟网络上面的编码方法有些类似。学过计算机网络的人都应该知道海明码
吧?不知道也不要紧,我简单介绍一下:
1.海明码的概念

海明码是一种可以纠正一位差错的编码。它是利用在信息位为k位,增加r位冗余位,构成一个n=k+r位

的码字,然后用r个监督关系式产生的r个校正因子来区分无错和在码字中的n个不同位置的一位错。它

必需满足以下关系式:

2^r>=n+1  或  2^r>=k+r+1

海明码的编码效率为:

R=k/(k+r)

式中 k为信息位位数

r为增加冗余位位数
2.海明码的生成与接收

1)海明码的生成。

例1.已知:信息码为:"0010"。海明码的监督关系式为:

S2=a2+a4+a5+a6

S1=a1+a3+a5+a6

S0=a0+a3+a4+a6

求:海明码码字。

解:1)由监督关系式知冗余码为a2a1a0。

2)冗余码与信息码合成的海明码是:"0010a2a1a0"。

设S2=S1=S0=0,由监督关系式得:

a2=a4+a5+a6=1

a1=a3+a5+a6=0

a0=a3+a4+a6=1

因此,海明码码字为:"0010101"

2)海明码的接收。

例2.已知:海明码的监督关系式为:

S2=a2+a4+a5+a6

S1=a1+a3+a5+a6

S0=a0+a3+a4+a6

接收码字为:"0011101"(n=7)

求:发送端的信息码。

解:1)由海明码的监督关系式计算得S2S1S0=011。

2)由监督关系式可构造出下面错码位置关系表:

S2S1S0

000

001

010

100

011

101

110

111

错码位置

无错

a0

a1

a2

a3

a4

a5

a6

3)由S2S1S0=011查表得知错码位置是a3。

4)纠错--对码字的a3位取反得正确码字:"0 0 1 0 1 0 1"

5)把冗余码a2a1a0删除得发送端的信息码:"0010"

  好了就介绍到这里,其实比较有用的就是那个编码思想,我们在后面用r位监督码来纠正k位的错误,只要能够通过r位二进制的2的r次方种情况把前面的错误情况都表示清楚了即可找到相应的错误位。
  上面的小狗的例子也是如此对应的,十只小狗可以表示1024种情况,足以验证1000个瓶子了,所以,可以用二进制编码来解决这个问题。
  然而这位网友在最后也提到了“可怜的小狗,你死得好冤哪。从人道主义角度来说,还是第一种办法
好,运气好的话10条小狗都不会死。第二种办法固然是节省时间,但是碰上111111111这种的,一下子得死9条狗,太残忍了”,所以呢,对于算法来说,还是需要优化的,不仅仅在时间复杂度上面优化,这次优化的应该算是“空间复杂度”上的优化吧,所以问题就来了,怎样测试可以在最坏的情况下让死的小狗最少呢?
  这个我们可以用类比的方法,我们可以用二进制编码,那么我们也可以用十进制进行编码啊,于是我们便产生了更加优化的一种方法:
 
 第一次,每只狗按照百位数对应的编号喝水,即第0号喝0XX号水。一个小时后,每只狗再按十位数对应的编号喝水。再过一个小时后,再按个位数编号喝水。
这样第20、21、22小时期间分别可以观测到3次中毒情况,每次中毒的狗的编号合起来就是有毒水瓶的编号。需要注意的是,如果只有一只狗中毒(比如编号为a),那么有毒水瓶的编号就是aaa。其他情况类推。
  这样最好情况下可以不死狗(000就是有毒水瓶),最坏情况下死3只。死狗的数学期望值小于3。每瓶水只需被喝3次。
这个办法是不是很帅?哈哈,小狗狗们有救了。当然可能用其他进制的数比如十六进制什么的或许也可以做,本人没有考虑,有兴趣的话,读者可以想想看^_^

其实呢,这些方法一般都应该是学过计算机的人想到的,而大部分没有学过计算机的我想有一部分人会想到去用混和溶液的方法吧?我也曾经想过类似的方法,其实跟上面的算法本质上还是一样的,下面写出一种比较好的混和的方法,供大家参考一下^_^
  把1000瓶水分成10份,每份100瓶,100瓶水分别取一点进行混合(因为哪怕只有一个有毒分子也会有效果),最终有10份混合水。这样10个小狗分别尝10份混合水,2个小时后一个小狗死亡,就可将有毒水缩小范围至100瓶水。接着依次办理把100瓶再分10份,每份10瓶组成混合水,9个小狗品尝其中9份混合水,如果2个小时后又有一个小狗死亡,则有毒水在其品尝的那份10瓶中,如果没有小狗死亡,则

有毒水就在没有小狗品尝的混合水中,总之范围有缩小至10瓶水。对于有毒水所在的这10瓶水,用剩下的8个小狗品尝其中的8瓶,如果2个小时后有小狗死亡,则他喝的水就是有毒水,如果没有死亡的小狗,则再用2个小狗去品尝剩余的2瓶水……
最终,最多需要8个小时即可,牺牲3个小狗就可以找到有毒水。

 

  好了,就写这么多了,有不同意见的跟帖好了,欢迎发表意见^_^ 

一些有趣的题目(整理版)

据说是Google的面试题目 ...
  • Minus8cool
  • Minus8cool
  • 2006年03月14日 21:30
  • 2324

[数据结构]一些有意思题目(一)

1,求两个数的最大公约数 int gcd(int i,int j) { while(i != j) { if(i > j) { i -= j; } else...
  • u013686805
  • u013686805
  • 2014年04月04日 17:40
  • 743

小狗的状态

小狗在不同环境条件下可能呈现不同的状态表现,要求用接口封装小狗的状态。 代码如下: interface DogState{ public void showState(); } cl...
  • come0913mice
  • come0913mice
  • 2017年12月02日 09:33
  • 117

契诃夫的大狗叫,小狗也叫

网上查到的大狗小狗论,真是契诃夫老哥的俄国作家契诃夫说,大狗叫,也得让小狗叫,咱们把自己当做小狗就是了。没有大狗凶猛,声音也比大狗小,可不能拿小狗不当狗啊!我们为什么而写作?契诃夫说,这个世界有大狗,...
  • lvjack
  • lvjack
  • 2006年02月12日 15:53
  • 7727

Java第6章-接口与多态实验2(小狗的状态)

实验目的: 面向接口编程的思想,所为面向接口编程,就是设计某种重要的类时,不让该类面向具体的类,而是面向接口,即所设计类中的重要数据是接口声明的变量而不是具体类声明的对象。 Dog.java publ...
  • qq_34216631
  • qq_34216631
  • 2016年10月16日 12:03
  • 1508

【JAVA】给大家推荐一道有意思的java测试题。你知道答案吗?

作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985, QQ986945193 公众号:程序员小冰public class Test { /** ...
  • qq_21376985
  • qq_21376985
  • 2016年09月01日 09:47
  • 1426

题目1 : 传话游戏

题目1 : 传话游戏 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 Alice和Bob还有其他几位好朋友在一起玩传话游戏...
  • zxdfc
  • zxdfc
  • 2014年04月07日 21:13
  • 1720

一些比较有意思的题目

递归问题往往存在子问题,本文中的递归问题不属于之前的专题,故单列一个专题。1.从一个n位数中寻找m位数,并输出最小值来源:面试一家创业公司的题目Example 输入:698592 k = 4 ...
  • a819825294
  • a819825294
  • 2016年09月01日 16:39
  • 1357

一些有趣的SQL题目

题目来自: 点击打开链接 下面是本人的答案: --一下语句中用到的表tb均指这个测试表 --1、你猜下面这条语句能得到什么结果,这个很常用 if object_id('tb') is not nu...
  • yenange
  • yenange
  • 2017年09月20日 10:29
  • 282

一段有趣的C++代码,五次选择猜出你的生日

程序代码:GuessBirthDate.cpp /** * 运行程序,做5次选择,就能知道你的生日是哪一天。 */ #include using namespace std; int ma...
  • qq_30062589
  • qq_30062589
  • 2017年02月01日 22:25
  • 1716
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:小狗喝水(好玩的题目^_^)
举报原因:
原因补充:

(最多只允许输入30个字)