【数学】用信息论去解决「小白鼠试毒」问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/haolexiao/article/details/72843286

试毒问题非常经典,最早是在本科时候人人上看到的,是最基础的1000个试剂,有一个是有毒的,一点就会死去,而且一个小白鼠只能试一次,问最少几个小白鼠能够找出哪瓶是有毒的。后来陆陆续续又看到了一些关于这方面的题,发现这个本质上相当于信息论中关于信息编码长度的问题。

通用方法是讲试剂中哪瓶是毒品的信息总数表示出来为N,然后再找出小白鼠所能表示的状态数目为M,则需要的小白鼠个数为: K=logNM
而具体实验的操作方法为:

  1. 讲每种状态按照M进制进行编码,编码长度为K
  2. 每个小白鼠分别去拿自身的M中状态去实验N的M进制编码的某一位
  3. 所以K个小白鼠,等同于是K长度M进制的对应的每一位
  4. 这样试验完后,就确定了每一位上面的数字,找到对应的那种状态就好。

初级版问题——每只只能试一次

就是引言中说的小白鼠那个问题。
因为每个小白鼠只够去试一次,所以,每只小白鼠身上有两种状态——死亡或者存活
而试剂中有毒的信息量为1000,即每瓶试剂都有可能有毒。
所以需要的编码长度为: log12000 向上取整得到10
所以操作如下:

  1. 1000瓶药二进制编码为10位数
  2. 10个小白鼠分别去实验,第 i 个小白鼠去实验,编码长度下第 i 位为1(或者为0)的全部试剂
  3. 根据小白鼠是被毒死还是存活,确定每一位的0/1值
  4. 这样就得到了一个10位长度的二进制编码,其对应的试剂就是有毒的

中级版问题——每只可以实验多次

这个问题最早是在股社区的微博那里看到的。

10000桶酒,其中1桶是毒酒;48小时后要举行酒会;毒酒喝下去会在之后的第23-24小时内毒死人(时间确定);国王决定用囚犯来试酒,不介意囚犯死多少,只要求用最少的囚犯来测试出哪一桶是毒酒,问最少需要多少囚犯才能保证找出毒酒?

根据题目要求,对于每个囚犯,其是可以实验24次的,即第0小时喝,然后第1小时再喝,。。。如果第K小时死亡,则是因为第K-24(上取整)小数喝的酒导致的。
这样的话,每个人就含有了25个状态,即24小时分别每个小时死亡,外加最后没有死。
所以需要的囚犯数为 log1000025=3
即将10000瓶酒按照25进制编码进行编码,是一个三位数长度的
然后三个人分别第i小时去喝对应位数上编码为i的所有酒
最后就能确定下来具体和哪一瓶酒。
股社区给了一个形象化的解释:

把酒摆成22*22*22的正方体,桶数不够空着就行,原题说喝一点就死,所以一个囚犯理论上可测试很多桶。每小时测试正方体一个面,也就是22*22=484桶,22个小时后测完所有的酒。每个囚犯从一个不同的侧面开始喝,等于是正方体的长宽高,最后三个囚犯都死了,根据死亡时间定位出那桶酒

类似的题还有知乎上的一道题:
1000桶水,其中一桶有毒,猪喝毒水后会在15分钟内死去,想用一个小时找到这桶毒水,至少需要几头猪?
即每个猪油5种状态,则5个猪即可完成编码。

高级问题——不止一瓶试剂有毒

不止一瓶试剂有毒的情况下,其实非常的复杂。
详见知乎上的这道题:
1000桶水中两桶有毒,猪喝毒水后会在15分钟内死去,想用一个小时找到毒水,至少需要几只猪?如何实现?
因为有两桶有毒,所以等于信息量为: N=C21000 种情况,每个猪身上有5种状态,所以最低有: logN5=9 但是这个只是理论下界,因为猪死亡是不能够区分出,是被一瓶毒药毒死的,还是两瓶毒药。
假设猪死亡的状态可以区分出来/或者两种毒药需要混合才能有毒性的话,那么做法是,将这1000瓶毒药两两混合,一共 N=C21000 种组合,然后将这些组合按照5进制进行编码。然后9头猪就可以区分出来了。

而对于这道题的解法呢,我觉得原答案中「小河流」的答案还是解释的比较清楚的,对于不值一瓶试剂有毒的情况,就是先用交叉法再用进制法。
即10头猪每个喝100瓶,然后按照死一头还是死两头进行分开讨论。具体如下:

作者:Miss老杨
链接:https://www.zhihu.com/question/60461214/answer/176619099
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我有一种用10只猪的方法:
1.给每只猪喂对应个位数编号的水,这样第一个15分钟后肯定最多死两只猪。
2.1.如果死了两只猪的话,则同时确定了两个一百桶水里有一桶水有毒。问题简化成一百桶水里有一桶有毒,试45min确定哪一桶。将剩下八只猪平均分开,利用镜像问题 @Sun AO 提供方法(即用几进制的四位数至少可以表示到100),分别确定这桶水。因为4*4*4*4>100。两步一共需要10只猪。
2.2如果仅死一只猪的话,问题变成100桶水里一桶有毒,45min确定哪两桶。利用1思路,给剩下每头猪喂9余数的水。
2.2.1若死两只猪(此时还剩下7只猪),则问题简化成12桶水一桶有毒,试30min确定。将剩下猪分成33两组。因为3*3*3>12。
2.2.2若死一只猪(此时还有八只猪),问题变成12桶水里一桶有毒,30min确定哪两桶。利用1思路,给剩下每头猪喂8余数的水。
2.2.2.1若死两只猪(此时还有六只猪),问题变成2桶水里一桶有毒,15min确定哪两桶。
2.2.2.2若死一只猪(此时还有七只猪),问题变成2桶水里一桶有毒,15min确定哪三桶。故而此方法10只是最多的。
PS.这个问题需要找到一个平衡点:在哪一步确定出剩下的水里面肯定有且仅有一桶有毒。因为确定一桶水的位置的速度是幂数级的,而将水分开的速度是阶乘级的,所以越早分开越好。显然每次死两只猪的过程是最浪费的。所以上限应该取决于此过程。如果是九只猪的话,剩下2个112桶水被确定有且仅有一桶毒水。将猪按3只和4只分开。但3只猪最多只能表示3*3*3*3=81只。
基此方法可以一劳永逸地解决n桶水里有k桶有毒,t时间内确定出来,至少需要l只猪的问题。不过根据理论计算:1000桶水里两桶有毒一共有499500个状态。而每只猪一个小时内共有5个状态(15 30 45 60min内死和不死),l只猪一共就有5^l个状态。即5^l>499500。l>8.15。也就是说有种方法可以只用九只猪。这种方法是基于将水两两组合,给每个组合编号,然后用5位l进制数去表示这些组合。但是我觉得这个理论值偏低,因为对于猪而言分不清究竟是一桶水毒死自己还是两桶?所以1000桶水两两混合之后,有毒的组合有1999种。问题转化为499500桶水里有1999桶有毒,试一小时确定,使得问题反而复杂了。

猜你喜欢

转载自blog.csdn.net/haolexiao/article/details/72843286