MATLAB编程解决1000瓶水的验毒问题

文章出自https://bbs.csdn.net/topics/340004129,算法叫做“平衡二叉树”,用matlab软件编的拿来学习下。
这个问题的模型就是用多少二进制位可以表示1000内的一个数字.回答这个模型就简单了,1000表示为二进制表示1111101000.最大的1000用10位就中了,那么检验这1000瓶水要10个小白鼠.

那么要怎么样检验呢.经过我在床上转来转去的思考,终于想到了一个方法.1000瓶水太多了,我们用8瓶水说明情况(要用3个小白鼠做实验哦).好像下面的图叫做平衡二叉树来的吧.名词忘记了,能用就中.



所有小白鼠只喝右分支的水(要是左的话水编号要从右到左增加). 也就是
鼠1喝水4,5,6,7的混合液体
鼠2喝水2,3,6,7的混合液体
鼠3喝水 1,3,5,7的混合液体

貌似水0没有老鼠喝,但愿一个白鼠都没有死就是你水0有毒了.

这样小白鼠死亡表示1,不死亡表示0。鼠1,鼠2,鼠3组成个三位二进制
000对应水0有毒
001对应水1有毒

111对应水7有毒
1000瓶水和这个原理一样用十个小白鼠就找到那瓶水有毒了.

感觉恍然大悟,所以编了下程序,不过问题已经不是求小白鼠数目了,而是对整个检测的过程进行了模拟,并且给出判断结果。

给1000个瓶分别标上如下标签(10位长度): 
0000000001 (第1瓶) 
0000000010 (第2瓶) 
0000000011 (第3瓶) 
...... 
1111101000 (第1000瓶) 
从编号最后1位是1的所有的瓶子里面取出1滴混在一起(比如从第一瓶,第三瓶,里分别取出一滴混在一起)并标上记号为1。以此类推,从编号第一位是1的所有的瓶子里面取出1滴混在一起并标上记号为10。现在得到有10个编号的混合液,小白鼠排排站,分别标上10,9,1号,并分别给它们灌上对应号码的混合液。24小时过去了,过来验尸吧: 

从左到右,死了的小白鼠贴上标签1,没死的贴上0,最后得到一个序号,把这个序号换成10进制的数字,就是有毒的那瓶水的编号。 

检验一下:假如第一瓶有毒,按照0000000001 (第1瓶),说明第1号混合液有毒,因此小白鼠的生死符为0000000001(编号为1的小白鼠挂了),0000000001二进制标签转换成十进制=1号瓶有毒;假如第三瓶有毒,0000000011 (第3瓶),第1号和第2号混合液有毒,因此小白鼠的生死符为00000011(编号为1,2的鼠兄弟挂了),0000000011二进制标签转换成十进制=3号瓶有毒。

main.m
================================================================
  1. clc
  2. clear
  3. N=8;%总瓶数 
  4. num=log2(N);%需要小鼠数
  5. pos=round(1+rand*(N-1));%毒药在第几瓶 从1开始
  6. solu=zeros(num,N/2);%方案
  7. for ii=1:num
  8.     solu(ii,:)=tiqu(N,ii);%每只小鼠喝哪几瓶 方案
  9. end
  10. result=zeros(num,1);%活 死
  11. for ii=1:num
  12.     result(ii)=ismember(pos,solu(ii,:));%0 活 1 死
  13. end
  14. code=result';%编码
  15. tdpos=bin2dec(num2str(code))+1;%推断的位置 
  16. disp('真实位置(毒药)');
  17. disp(pos);
  18. disp('推断位置(毒药)');
  19. disp(tdpos);
  20. disp('小鼠状态(0-活,1-死)')
  21. disp(result);
复制代码
tiqu.m
================================================================
  1. function a=tiqu(A,no)
  2. % A 瓶子总数目
  3. % no 第no只小鼠
  4. % a  第no只小鼠应该喝哪些瓶子里的东西
  5. if no>log2(A)
  6.     error('超出最大数目');
  7. end
  8. fenduan=2^no;%分段数
  9. lenduan=A/fenduan;%段长度
  10. AA=zeros(fenduan,lenduan);%每段内容 包含的序号
  11. Aa=zeros(fenduan/2,lenduan);%第no只小鼠喝的序号的矩阵 
  12. for ii=1:fenduan
  13.     AA(ii,:)=[(ii-1)*lenduan+1:1:ii*lenduan];
  14. end
  15. Aa=AA(2:2:end,:);%Aa取为AA的偶数行的值
  16. Aa=Aa';
  17. a=Aa(:);
  18. a=a';
  19. end
复制代码
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭