不要放弃治疗——喂药问题小结

算法设计问题描述:

1.在1000个药瓶中有唯一一瓶毒药,现要求用尽量少的小白鼠做实验来找出那唯一的一瓶毒药;

2.若小白鼠吃到毒药则死亡,否则不死,不同的药瓶中的药可以混合喂给小白鼠,混合药中含毒药则小白鼠死,不含毒药则不死;

3.若药效产生的时间很长,现要求在一次药效产生的时间内找出毒药,问:最少需多少只小白鼠?


对这个问题,我们首先能想到的是,1000个瓶子中只有一瓶毒药,那么有1000种可能性,对于一直小白鼠而言,吃药之后只能有两种情况,要么死,要么不死,那么假设有一只小白鼠吃了由 n 瓶药混合而成的药,①死了,则排除了1000-n种可能性,即毒药一定在参与混合的n瓶药之中;②没死,则同理排除了n种可能性;为了保证算法在最坏的情况下依旧能有较好的运行表现,那么对可能性的排除一定要是均衡的,(参考:快排为什么快)即:我们应该采用二分法来解决这个问题;

到这里问题都很简单,可是题目还有一个额外的要求:在一次药效产生的时间内找出毒药。也就意味着:没有一次又一次通过排除可能性来选择下一次二分的机会。那么怎么做呢?难道得用999只小白鼠才能一次找出有毒的那瓶药吗?


要在一次药效产生的时间内找出毒药,意味着药效产生后,我们能够通过实验小白鼠的结果(死或者不死)来推断出排除的所有可能性;给出算法入下:

1.将1000瓶药按二进制进行编号,需要lg[1000](取上整数)=10位二进制;

2.找10只小白鼠编号为1~10;

3.i从1到10,将药瓶编号第 i 位二进制数为1的所有药瓶中的药混合后喂给编号为 i 的小白鼠,药效生效后观察小白鼠生命情况;

4.分析小白鼠生命情况,得到一个10位二进制数,其每一位如下确定,若第 i 只小白鼠死,则该二进制数的第 i 位为1,否则为0;

5.得到的10位二进制数编号对应的药瓶中即为毒药;

所以最少需要小白鼠10只;


下面我们对这个算法进行分析:

在我们最初的思考中,对二分法的考虑需要每次二分的结果出来后才能选择下一次二分的范围;而上述算法中,通过二进制编号,二进制的每一位都对应着一次二分,故10次二分同时进行,但这种二分的过程与我们最初思考的二分又有一些不同,在我们最初所想的二分法中,每次二分所能排除的可能是折半的,即:通过上一次二分排除一半可能性后下一次二分就在剩下的一半可能性中进行;而算法中的二分每一次范围都是1000,解释如下:对于一个10位二进制的每一位,为1的跟为0的药瓶数差不多相等,即近似为500(因为1000不是2的幂,故近似为一半),如:编好号后,最低位为1的瓶子有500个,最低位为0的瓶子有500个(高位也一样,但可能不是精确的500);当10只小白鼠按要求吃药后,根据生命情况就能确定一个唯一的10位二进制数,如:单独看一只小白鼠,若1号小白鼠死,则最低位为1,排除了最低位为0的情况,即排除了500种可能,对于单独看其它编号的小白鼠也一样,即可以排除一半的可能性,而得到10位二进制数时是整合一起看的,如:1号小白鼠死亡,最低位为1,剩下500种情况,此时发现2号小白鼠也死亡,即第二位为1,由于第一位已经为1,所以第二位又为1,则剩余的可能情况即为在编号中最低位为1的药瓶中第二位也为1的药瓶,即在500中情况中又排除250种情况,依次类推,最终得到唯一的一个瓶子的编号;二分的结果通过二进制位为1或0进行记录,最终实现了一次药效时间内出结果。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值