“1000瓶药水,其中至多有1瓶剧毒,小狗服完药20小时后才能判断是否中毒。现在给你10只小狗、在24小时内、通过小狗试药的方式找出哪瓶药有毒或者全部无毒”
2011-09-27 09:10
363 查看
题目:
1000瓶药水,其中至多有1瓶剧毒,小狗服完药20小时后才能判断是否中毒。
现在给你10只小狗、在24小时内、通过小狗试药的方式找出哪瓶药有毒或者全部无毒
思路:
一、“小狗服完药20小时后才能判断是否中毒”,现只有“24小时内”,那么只能试一轮。
二、一轮过后,每只小狗状态有两种:生、死
把每只狗看成二进制数的一位,那么结果是个10位的二进制数,可表示2^10 即1024种情况
这已经超过了目标总数(1000),因此有可能找到一种编码方案,将1000种情况唯一的表现出来。
三、将1000瓶药编号:1~1000,换成2进制:0000000001至1111101000(称最左边为第9位,最右边为第0位)
再取10个试管,编号:9876543210
对每瓶药,查它2进制编号中所有为1的位,按位序号加到对应试管中。
例如第1000瓶药的编号为1111101000,加入第9,8,7,6,5,3号试管。
然后对狗编号,吃下对应试管的药(混合后的)。
四、20小时后,根据狗的情况:生=0,死=1 得到一个10位2进制数,即毒药的编号。
以下为测试程序:
1000瓶药水,其中至多有1瓶剧毒,小狗服完药20小时后才能判断是否中毒。
现在给你10只小狗、在24小时内、通过小狗试药的方式找出哪瓶药有毒或者全部无毒
思路:
一、“小狗服完药20小时后才能判断是否中毒”,现只有“24小时内”,那么只能试一轮。
二、一轮过后,每只小狗状态有两种:生、死
把每只狗看成二进制数的一位,那么结果是个10位的二进制数,可表示2^10 即1024种情况
这已经超过了目标总数(1000),因此有可能找到一种编码方案,将1000种情况唯一的表现出来。
三、将1000瓶药编号:1~1000,换成2进制:0000000001至1111101000(称最左边为第9位,最右边为第0位)
再取10个试管,编号:9876543210
对每瓶药,查它2进制编号中所有为1的位,按位序号加到对应试管中。
例如第1000瓶药的编号为1111101000,加入第9,8,7,6,5,3号试管。
然后对狗编号,吃下对应试管的药(混合后的)。
四、20小时后,根据狗的情况:生=0,死=1 得到一个10位2进制数,即毒药的编号。
以下为测试程序:
#include <cassert> #include <cstdlib> #include <cstring> #include <iostream> using namespace std; class Tester { bool m_began; int m_poison; bool m_dogs[10]; public: Tester() : m_began(false) { this->begin(); this->end(); } void begin(int i = -1) { m_began = true; memset(m_dogs, 0, sizeof(m_dogs)); m_poison = (i == -1 ? (rand() % 1000) + 1 : i); } void feed(int dog0to9, int bottle1to1000) { assert(m_began); if(bottle1to1000 == m_poison){ m_dogs[dog0to9] = true; } } void end() { m_began = false; } bool query(int dog0to9) { assert(!m_began); return m_dogs[dog0to9]; } void judge(int poison) { assert(!m_began); if(m_poison != poison){ cerr << "test failed: estimate " << poison << ", fact " << m_poison << endl; exit(0); } } }; void testCase(Tester & t, int x = -1) { t.begin(x); for(int i = 1; i <= 1000; ++i){ // for each bottle for(int x = i, n = 0; x; x >>= 1, ++n){ // each bit if(x & 1){ t.feed(n, i); } } } t.end(); int id = 0; for(int i = 9; i >= 0; --i){ id = (id << 1) | (t.query(i) ? 1 : 0); } t.judge(id); } int main() { Tester t; // cover for(int x = 0; x < 1001; ++x){ testCase(t, x); } // random test for(int x = 0; x < 100; ++x){ testCase(t); } cout << "passed" << endl; return 0; }
相关文章推荐
- “1000瓶药水,其中至多有1瓶剧毒,小狗服完药20小时后才能判断是否中毒。现在给你10只小狗、在24小时内、通过小狗试药的方式找出哪瓶药有毒或者全部无毒”
- 有1000瓶药水,其中只有一瓶有毒。现在用小白鼠进行实验,小白鼠只要服用任意量有毒药水就会在24小时内死亡。问至少要用多少只小白鼠进行实验才能检测出哪瓶药水有毒?
- 1000瓶酒其中1瓶有毒,10只老鼠找出毒酒
- 面试题:1000瓶水其中有一瓶水有毒,有10只老鼠并且只要老鼠喝了有毒的水必死。请问怎样通过一次实验找出有毒的那瓶水。
- 现有8种药水,其中有且仅有一种有毒,药水24小时见效,现在要求在24小时内找出有毒药水,需要至少几只小白鼠?
- 1000瓶药有1瓶有毒,需要多少只小白鼠才能试验找出
- 关于10只狗测1000瓶药水有毒无毒的问题
- 1000瓶药有1瓶有毒,需要多少只小白鼠才能试验找出
- 通过包名判断手机上是否安装了QQ,微信,或者其他应用
- 有1000瓶水,其中有一瓶有毒,小白鼠只要尝一点带毒的水24小时后就会死亡至少要多少只小白鼠才能在24小时
- 有10狗,1000瓶药水,其中有一瓶有毒,狗喝一下点就会死,请问怎么找到1000瓶中有毒的那一瓶?
- 对给定的字符串(只包含'z','o','j'三种字符),判断他是否能AC。 是否AC的规则如下: 1. zoj能AC; 2. 若字符串形式为xzojx,则也能AC,其中x可以是N个'o' 或者为空;
- 通过IWebBrowser2的Navigate2来打开网页,怎样判断网页是否全部加载完毕
- 1000瓶药,至多1瓶有毒,用10条狗(老鼠)试毒的面试题
- ACM找出一串数字是否能被分成两部分使其中一部分全部为负数,加上另一部分可以为0
- MVC中通用JS判断表单或者某个具体的文本框验证是否通过
- 有1000桶酒,其中1桶有毒。而一旦吃了,毒性会在1周后发作。现在我们用小老鼠做实验,要在1周后找出那桶毒酒,问最少需要多少老鼠,如何检测?
- 通过IWebBrowser2的Navigate2来打开网页,怎样判断网页是否全部加载完毕
- PHP判断表单是否通过post方式提交
- 8种药水有且仅有一种有毒,药水1小时见效,现在要求在1小时内找出有毒药水,至少需要几只小白鼠?