【每天进步一点】毒药和老鼠的研究
2015-04-09 15:44
274 查看
之前碰到过毒药和老鼠,鸡蛋和称的问题,每次都拿笔在纸上推敲很久,这类问题今天终于有了完整的解决思路。
基础:
1.整数的二进制表达式
1000的二进制表达式是什么呢?
1000的二进制表达式为 1111101000 = 29 + 28 + 27 + 26 + 25 + 23 = 512 + 256 + 128 + 64 +32 + 8
还需要其他的吗?不需要了,有上面的基础足矣。
二进制和上面的题目有什么关系呢?
在计算机基础里面,函数B2Uw表示Binary to Unsigned(长度为w的二进制到无符号整数),它能够被定义为一个映射:
B2Uw{0,1}w --> {0,1,...,2w-1}
也就是说表达0~2w-1的整数值,只需要w位的二进制即可。
再转换一下:w位的二进制可以表达(2w-1)+1=2w个整数值。
反应在我们的命题中,n个瓶子对应n个可能的结果,转换成二进制之后,只需要x位的0101就可以表达出来了。(n已知,x未知。x的求值参考上面的结论)
命题:8瓶水,其中一瓶有毒,中毒的老鼠会在一个星期之后死亡。给你一个星期,请问最少几只老鼠可以测试出哪瓶有毒?
步骤一:确定需要几只老鼠
8 = (二进制)1000 = 23。
即三位的二进制即可表达8种情况。
步骤二:为药品分配准备数据
将三位的二进制所有的情况罗列出来,剔除0的情况
计算机的整数(索引)从0开始,生活中的计数习惯从1开始。而实际的操作中,我们可以拿出一瓶不做测试,当所有老鼠都存活下来时,就说明拿出来的这一瓶是最后的结果。这里可以取个巧,将0理解为索引,映射到最后一个数字,在这里就是8;剔除0,也就是剔除了第8瓶水的情况。
从右往左,第一列对应的是1010101,其中1对应的数即为{1,3,5,7};第二列对应0110011=>{2,3,6,7};第三列对应0001111=>{4,5,6,7}
步骤三:提取上面的数字,得出喂食方案。
第一只老鼠给他喂食(1,3,5,7)瓶水的混合液,第二只老鼠喂食(2,3,6,7)的混合液,第三只老鼠喂食(4,5,6,7)的混合液。
View Code
发散的问题:6个质量相等的小球和1个质量稍重的球,不能用天平,只能用称,设计一种方法,只能量三次就找出稍重的球。
类似的问题,这里数量变成了7个。测试数据也从死掉变成了重和轻,不过一样可以转换成0和1。
如果你看懂了上面,不妨想想这个的答案。
基础:
1.整数的二进制表达式
1000的二进制表达式是什么呢?
1000/2=500 --(余)--0 500/2=250 --(余)--0 250/2=125 --(余)--0 125/2=62 --(余)--1 62/2=31 --(余)--0 31/2=15 --(余)--1 15/2=7 --(余)--1 7/2=3 --(余)--1 3/2=1 --(余)--1 1/2=0 --(余)--1
1000的二进制表达式为 1111101000 = 29 + 28 + 27 + 26 + 25 + 23 = 512 + 256 + 128 + 64 +32 + 8
还需要其他的吗?不需要了,有上面的基础足矣。
二进制和上面的题目有什么关系呢?
在计算机基础里面,函数B2Uw表示Binary to Unsigned(长度为w的二进制到无符号整数),它能够被定义为一个映射:
B2Uw{0,1}w --> {0,1,...,2w-1}
也就是说表达0~2w-1的整数值,只需要w位的二进制即可。
再转换一下:w位的二进制可以表达(2w-1)+1=2w个整数值。
反应在我们的命题中,n个瓶子对应n个可能的结果,转换成二进制之后,只需要x位的0101就可以表达出来了。(n已知,x未知。x的求值参考上面的结论)
命题:8瓶水,其中一瓶有毒,中毒的老鼠会在一个星期之后死亡。给你一个星期,请问最少几只老鼠可以测试出哪瓶有毒?
步骤一:确定需要几只老鼠
8 = (二进制)1000 = 23。
即三位的二进制即可表达8种情况。
步骤二:为药品分配准备数据
将三位的二进制所有的情况罗列出来,剔除0的情况
计算机的整数(索引)从0开始,生活中的计数习惯从1开始。而实际的操作中,我们可以拿出一瓶不做测试,当所有老鼠都存活下来时,就说明拿出来的这一瓶是最后的结果。这里可以取个巧,将0理解为索引,映射到最后一个数字,在这里就是8;剔除0,也就是剔除了第8瓶水的情况。
┆ 0 ┆ 0 ┆ 1 ┆ //1 ┆ 0 ┆ 1 ┆ 0 ┆ //2 ┆ 0 ┆ 1 ┆ 1 ┆ //3 ┆ 1 ┆ 0 ┆ 0 ┆ //4 ┆ 1 ┆ 0 ┆ 1 ┆ //5 ┆ 1 ┆ 1 ┆ 0 ┆ //6 ┆ 1 ┆ 1 ┆ 1 ┆ //7
从右往左,第一列对应的是1010101,其中1对应的数即为{1,3,5,7};第二列对应0110011=>{2,3,6,7};第三列对应0001111=>{4,5,6,7}
步骤三:提取上面的数字,得出喂食方案。
第一只老鼠给他喂食(1,3,5,7)瓶水的混合液,第二只老鼠喂食(2,3,6,7)的混合液,第三只老鼠喂食(4,5,6,7)的混合液。
Console.WriteLine("假设有毒瓶数为:"); int poisonOne = int.Parse(Console.ReadLine()); Console.WriteLine("死掉的老鼠有:" + string.Join(",", solution.Select((aa, idx) => aa.Contains(poisonOne) ? idx + 1 : -1).Where(idx => idx != -1))); var resBinary = new string(solution.Select(aa => aa.Contains(poisonOne) ? '1' : '0').Reverse().ToArray()); Console.WriteLine("二进制表达式为:" + resBinary); var res = Convert.ToInt32(resBinary, 2); if (res == 0) res = poisonNum; Console.WriteLine("测试结果为:第{0}瓶有毒", res);
View Code
发散的问题:6个质量相等的小球和1个质量稍重的球,不能用天平,只能用称,设计一种方法,只能量三次就找出稍重的球。
类似的问题,这里数量变成了7个。测试数据也从死掉变成了重和轻,不过一样可以转换成0和1。
如果你看懂了上面,不妨想想这个的答案。
相关文章推荐
- dailynote1.29(每天进步一点,一定会有机会做项目的)
- 每天进步一点7
- 每天学习一个知识点,每天进步一点
- 每天一点进步:hbase预分区和压缩
- C#每天进步一点--异步编程模式
- 工作8年对技术学习过程的一些 总结 与 感悟 为什么有时迷茫、无奈 学习编程语言的最高境界最重要的是编程思想 T 字发展 学技术忌讳”什么都会“ 每天进步一点等式图 时间管理矩阵
- 每天进步一点之Qt--写给以后
- 每天进步一点
- 大二软件狗初次前来报到,每天自学一点j2e,每天进步一点点。
- 每天学习一点,进步一点!
- [每天进步一点 -- 流水账]系列说明
- 每天进步一点:java enum使用
- 每天进步一点5
- 给自己点压力,让自己每天进步一点
- [每天进步一点 -- 流水账]第3周
- 每天进步一点2
- 每天进步一点3
- 每天进步一点
- 每天进步一点之C\C++
- 每天一点进步:Spark运行模式和原理