关闭

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

1718人阅读 评论(1) 收藏 举报
有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个小狗就可以找到有毒水。

 

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

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:29785次
    • 积分:505
    • 等级:
    • 排名:千里之外
    • 原创:11篇
    • 转载:22篇
    • 译文:0篇
    • 评论:9条
    文章存档
    最新评论