您的位置 首页 婚恋情感

有1000杯水是有毒的吗?问题初步求解

有1000杯水,其中1杯有毒。 老鼠只要喝下一滴毒药,就会在两小时内死亡。

假设每杯有足够的水并且有足够的采样设备。

如果只需要2小时,需要多少只老鼠才能找出哪杯水有毒?

问题分析1

这个问题比较直观,也容易理解。 解决这个问题的算法的好坏可以通过两个因素来评价:时间成本和鼠标成本。

显然,该问题对时间和鼠标成本都有要求。 可以选择先找到一个直观的算法,然后对直观的算法进行分析和改进,得到符合要求的算法。

问题的初步抽象

对于水:我从0开始为每杯水编号,0为第一杯水的编号,999为第1000杯(最后一杯)水的编号。 另外,为了描述方便,将0号杯水简称为0号水,其他编号的各杯水亦同。

对于小鼠:我对每只消耗的小鼠从0开始编号,以0作为第一个消耗的小鼠的编号,其他编号的小鼠以此类推。

问题的初步解决方案

秉承循序渐进的原则,不考虑时间成本,也不考虑老鼠的成本。

那么问题就可以变成如何花费一定的时间和一定数量的老鼠从1000杯水中找出有毒的那杯水。

这个问题很直观,很容易找到下面的算法:

直观的算法1

1. 用1只小鼠从第一杯水开始喝水,喝完水后等待2小时。

2. 如果老鼠在2小时后死亡,那么老鼠2小时前喝的这杯水是有毒的。 如果没有死,老鼠会继续喝1杯水,直到喝完最后一杯水或死亡。

直观算法2

1. 使用 1,000 只小鼠。 每只小鼠喝一杯与自己相同数量的水,喝完水后等待2小时。

2. 2小时后毒水,老鼠喝下的这杯水是有毒的。

算法1评估

最差时间成本:2000小时(可改善至1998小时)

老鼠数量成本:1

算法2评估

最差时间:2小时

老鼠成本:1000只(当然可以提高到999只)

问题分析2

上述两种算法直观,但效率不高。 由于算法2比算法1更接近问题需求(只需要2个小时),所以这里我们重点对算法2进行分析和改进。

算法2之所以需要1000只老鼠,是因为每只老鼠只喝了1杯水。 也就是说,1只老鼠只存储了一杯水是否有毒的信息。 如果能让每只老鼠喝更多杯水,从而存储更多关于水是否有毒的信息,那么老鼠的成本就可以降低。

当有4杯水时,你可以用2只老鼠找到有毒的那杯水; 0号小鼠可以同时喝0号和1号水,1号小鼠可以同时喝0号和2号水。 根据0号和1号老鼠的“反应”找到那杯有毒的水。 具体来说:如果两只老鼠都死了,那么这杯毒水就是0号; 如果两只老鼠都存活下来,那么这杯有毒的水就是第三杯; 如果0号老鼠存活,1号老鼠死亡,则2号水和1号水有毒; 如果1号老鼠存活,0号老鼠死亡,则1号水有毒。 由此可以得出结论,需要2只老鼠才能找到4杯水中有毒的1杯。

按照这个方法,需要花费500只老鼠才能解决这个问题! 至此,就得到了一个新的算法,这里称为算法3!

算法3

使用500只小鼠,每组2只小鼠,共250组

1、0号小鼠喝0号水和1号水; 1号小鼠喝0号和2号水。

2号大鼠喝4号和5号水; 3号老鼠喝4号和6号水。

……

直到,498号老鼠喝了号水; 499号老鼠喝号水

2.当一只老鼠死亡时,可以根据同组中另一只老鼠的存活情况来找到这杯有毒的水。

算法3评估

最差时间:2小时

老鼠数量成本:500

问题分析3

算法3:根据任意一组小鼠的生存状况,只能判断该组小鼠喝下的水是否有毒,而无法帮助判断其他数量的水。

4杯水的问题可以由2只老鼠一组来解决。 所以这里假设1000杯水的问题也被一组N只老鼠解决了。 任意1杯水是否有毒,都是由这N只老鼠共同决定的!

问题进一步抽象

老鼠喝水的话用0表示,不喝水的话用1表示;

存活用1表示,小鼠死亡用0表示,

所有饮水条件和生存条件按照小鼠数量从左到右排列;

当有4杯水时,使用2只小鼠。

对于0号水,两只老鼠都喝了,定义为0, 0

对于1号水,0号老鼠喝了它,但1号老鼠不喝它,定义为0,1

对于2号水,0号小鼠没有喝它,但是1号小鼠喝了它,定义为1,0

对于3号水,0号小鼠不喝,1号小鼠也不喝,定义为1,1

可以将水数0~3改成如下的二进制形式:

00,

01,

10、

11

小鼠饮水情况为:

0号大鼠喝0号水和1号水;

1号大鼠喝0号和2号水;

老鼠的生活条件有四种:

0号小鼠死亡,1号小鼠死亡; 用0,0表示,此时0号水是有毒的。

0号小鼠死亡,1号小鼠存活; 用0和1表示,此时1号水是有毒的。

0号小鼠存活,1号小鼠死亡; 用1,0表示,此时2号水有毒。

0号小鼠存活,1号小鼠存活; 以1,1表示,此时3号水是有毒的。

可以发现,两只小鼠的生存状态与水数是对应的。

这里可以把生存情况当成二进制,转成十进制。 此时,其值为有毒的一杯水的数量。

当有8杯水时,根据以上结论。 使用 4 只老鼠可以让你找到那杯有毒的水,但这不太可能是一个有效的方法,因为 8 杯水被分为 2 个不同的组。 难道只有用3才能找到吗? 假设能查到,这里根据4杯水的处理方法推导一下:

对于0号水,0、1、2号小鼠都喝了,定义为0、0、0。

对于1号水,0号小鼠喝水,1号小鼠喝水,2号小鼠不喝水,定义为0,0,1

对于2号水,0号小鼠喝水,1号小鼠不喝水,2号小鼠喝水,定义为0,1,0

对于3号水,0号小鼠喝了,1号小鼠不喝,2号小鼠不喝,定义为0,1,1

对于4号水,0号小鼠不喝,1号小鼠喝,2号小鼠喝,定义为1,0,0

对于5号水,0号小鼠不喝水,1号小鼠喝水,2号小鼠不喝水,定义为1,0,1

对于6号水,0号小鼠不喝水,1号小鼠不喝水,2号小鼠喝水,定义为1,1,0

对于7号水,0、1、2号小鼠不喝,定义为1、1、1

小鼠饮水情况为:

0号大鼠喝0、1、2、3号水;

1号大鼠喝0、1、4、5号水;

2号大鼠喝0、2、4、6号水;

老鼠的生存条件有8种:

0号小鼠死亡,1号小鼠死亡,2号小鼠死亡; 用0,0,0表示,此时0号水是有毒的。

0号小鼠死亡,1号小鼠死亡,2号小鼠存活; 用0、0、1表示,此时1号水是有毒的。

0号小鼠死亡,1号小鼠存活,2号小鼠死亡; 用0、1、0表示,此时2号水有毒。

0号小鼠死亡,1号小鼠存活,2号小鼠存活; 用0、1、1表示,此时3号水有毒。

0号小鼠存活,1号小鼠死亡,2号小鼠死亡; 用1、0、0表示,此时4号水有毒。

0号小鼠存活,1号小鼠死亡,2号小鼠存活; 用1、0、1表示,此时5号水是有毒的。

0号小鼠存活,1号小鼠存活,2号小鼠死亡; 用1、1、0表示,此时6号水是有毒的。

0号小鼠存活,1号小鼠存活,2号小鼠存活; 用1、1、1表示,此时7号水是有毒的。

至此,8杯水的问题可以用3只老鼠解决。

2只小鼠的4种生存情况分别对应4杯水的数量;

3只小鼠的8种生存情况分别对应8杯水的数量。

当有N只老鼠时,由于每只老鼠有两种生存情况:0和1,所以总共有2种N次方生存情况,可以解决大小2的N次方问题。

当N为10时,有1024种生存情况。

此时,对于 1000 杯水,只需要 10 只老鼠就可以找到这杯有毒的水。

算法4

1000杯水,用10只老鼠,

将每杯水的编号从0到999以二进制形式写出

从 到 对于每 1 杯水,每 1 杯水以 10 位二进制形式编号,从左到右分别描述为第 1 到第 10 位数字。

0号老鼠喝的是第一位为0的二进制数对应的水。

1号老鼠喝的是第二位为0的二进制数对应的水。

……

8号老鼠喝的是第九位为0的二进制数对应的水。

9号老鼠喝的是第10位为0的二进制数对应的水。

2小时后,将表示生存状态的10位二进制数转换成十进制数,查出毒水的编号。

算法4评估

最差时间:2小时

老鼠成本:10只

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注