老鼠测试药物问题
原题:有1000种药,已知其中(只)有一种有毒,老鼠吃了会在一年之后死亡。现在的问题是,至少要多少只老鼠来做试验,才能在最短的时间内判断出来哪一种药物是有毒的?
思考:因为要在最短的时间内找出有毒药物,所以用1000只老鼠每只老鼠吃一种药,那肯定是能够在1年之后,知道哪一种药物有毒了。但是题目的要求是老鼠最少,另外还要时间上最快。所以不能说,一只老鼠今天吃这一种,明天吃另外一种,靠打时间差来判断。
那要怎样在时间最快的前提下减少老鼠的使用数量呢??
我们先将药物的种类弄少一点。如果只有2种药,其中有一种有毒,需要几只老鼠?
心直口快的人,可能马上就会说2只老鼠!
思考一下我们就知道:如果是2只老鼠,必然是一只死亡,一只存活,死亡的那只吃的那种药就是有毒的。细心的人已经想到了,其实一只老鼠就够了嘛,吃了某种药不死,那么这种药就没有毒,另外一种就是有毒的。
这个思路拓展一下就是有一种药其实是可以不吃的,依靠排除法就知道这种药有没有毒。
所以很容易想到,如果是3种药,2只老鼠就可以满足要求。1只行不行?心中盘算一下,是不行的。:)
如果是4种药呢?至少需要几只老鼠??
首先我们知道3只老鼠是可以完成测试任务的。那可不可以再减少老鼠呢?
1只老鼠有没有可能同时吃多种药呢?!
如果某只老鼠同时吃了2种药的话,它要是活着还好办,说明吃的2种药都无毒,要是死了的话,说明2种药里面肯定有一种是有毒的。那要怎么确定是哪一种呢?光靠这只老鼠是无法判断出来的,这个时候我们就要看其他老鼠的情况。
我们先让第一只老鼠吃第一种药,第二只老鼠吃第二种药,接下来该如何继续呢?
有一种药是可以不吃的,用排除法,假设其他所有药吃了都没事,那就说明没吃的那种药是有毒的。
所以,我们把第4种药放在一边,定为使用排除法判断的药,不用让任何一只老鼠吃。
现在:
老鼠1吃了药物1 ,老鼠2吃了药物2。第3种药物该怎么办呢?我们看看,是否能让两只老鼠都吃呢?!
也就是,老鼠1吃药物1,3。老鼠2吃药物2,3。
2只老鼠的结果会有4种情况:
老鼠情况 | 得出结论 |
老鼠1没死,老鼠2没死 | 药物4有毒 |
老鼠1没死,老鼠2死 | 药物2有毒 |
老鼠1死,老鼠2没死 | 药物1有毒 |
老鼠1死,老鼠2死 | 药物3有毒 |
从图中我们可以看出,2只老鼠就已经能判断出哪种药有毒了。
这种方法能不能推广呢?答案是肯定的。我们可以将每只老鼠看成2进制里面的一个位。老鼠可以吃多种药(具体该怎么吃,下文分析),结果只有2种状态,死或没死,死了就把老鼠代表的这个位置为1,没死就置为0。
因为2个二进制位可以表示4种情况(00,01,10,11),所以2只老鼠就可以测试出来4种药中,哪一种有毒了。
我们把上面的图改进一下,2个老鼠用2个位表示,老鼠死了,位=1,老鼠没死,位=0。然后把药从0开始编号,4种药用0-3的数字表示。
二进制数值 | 十进制数值 |
00 | 0 |
01 | 1 |
10 | 2 |
11 | 3 |
这也解决了我们在处理这类问题时的编码问题(该怎样给每只老鼠吃哪几种药?)
编码方案
通过上面2只老鼠4种药的分析,我们得出这样的编码方案:对于N种药,我们只需要log2N(向上取整)只老鼠,然后将药编号为0至N-1。将0至N-1都表示为二进制数值。然后看每个数的每1位,如果该位为1,那么这种药物就该给对应位的老鼠吃。比如4种药,第3种药需要喂给1,2两只老鼠吃,因为3的二进制为11,在2个位上都是1,所以两只老鼠都要吃。第二种药因为2的二进制位10,所以只需要喂给第二只老鼠吃。
我们可以通过这套编码方案,来试试8种药的测试方法。此时需要3只老鼠。
3只老鼠分别占据二进制的第0,1,2位 | 8种药的编号 |
000 | 0 |
001 | 1 |
010 | 2 |
011 | 3 |
100 | 4 |
101 | 5 |
110 | 6 |
111 | 7 |
比如第1只老鼠该吃的药,我们只需要看二进制数值列表的第0位为1的行。所以老鼠1应该吃1,3,5,7种药。同样,老鼠2该吃2,3,6,7种药,老鼠3该吃4,5,6,7种药。
同样我们可以看哪种药应该给哪个老鼠吃,药的编号对应的二进制中,位为1就应该给对应这个位的老鼠吃这种药。
比如编号2的药给第2只老鼠吃(2的二进制位010)。编号7的药应该给1,2,3只老鼠都吃,因为7的二进制位111,每一位都是1。
那么最后如何根据老鼠死的情况来判断哪种药有毒呢?
这个也很简单,只需要把每只老鼠对应的位做一个或操作就可以了。例如第1,3只老鼠死了,那么得到的二进制就是101,十进制为5,也就是说编号为5的药有毒。
老鼠都没死,得到的二进制数值是000,也就是0号药有毒(实际上是没有哪只老鼠吃到这种药= =)。老鼠都死了,那么就是111,也就是7号药有毒,这种药所有老鼠都吃了。
所以对于题中1000种药,至少需要10只老鼠才行。(log以2为底的1000向上取整=10)
问题延伸
如果有2种药是有毒的,该怎样设计测试方案呢?
如果允许测试的时间*2呢?http://blog.csdn.net/ryvipa/article/details/8764332