“1000瓶药水,其中至多有1瓶剧毒,小狗服完药20小时后才能判断是否中毒。现在给你10只小狗、在24小时内、通过小狗试药的方式找出哪瓶药有毒或者全部无毒”

题目:

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进制数,即毒药的编号。

以下为测试程序:

  1. #include <cassert>  
  2. #include <cstdlib>  
  3. #include <cstring>  
  4. #include <iostream>  
  5. using namespace std;  
  6.   
  7. class Tester  
  8. {  
  9.   bool  m_began;  
  10.   int   m_poison;  
  11.   bool  m_dogs[10];  
  12.   
  13. public:  
  14.   Tester()  
  15.     : m_began(false)  
  16.   {  
  17.     this->begin();  
  18.     this->end();  
  19.   }  
  20.   
  21.   void begin(int i = -1)  
  22.   {  
  23.     m_began = true;  
  24.     memset(m_dogs, 0, sizeof(m_dogs));  
  25.     m_poison = (i == -1 ? (rand() % 1000) + 1 : i);  
  26.   }  
  27.   
  28.   void feed(int dog0to9, int bottle1to1000)  
  29.   {  
  30.     assert(m_began);  
  31.     if(bottle1to1000 == m_poison){  
  32.       m_dogs[dog0to9] = true;  
  33.     }  
  34.   }  
  35.   
  36.   void end()  
  37.   {  
  38.     m_began = false;  
  39.   }  
  40.   
  41.   bool query(int dog0to9)  
  42.   {  
  43.     assert(!m_began);  
  44.     return m_dogs[dog0to9];  
  45.   }  
  46.   
  47.   void judge(int poison)  
  48.   {  
  49.     assert(!m_began);  
  50.     if(m_poison != poison){  
  51.       cerr << "test failed: estimate " << poison << ", fact " << m_poison << endl;  
  52.       exit(0);  
  53.     }  
  54.   }  
  55. };  
  56.   
  57. void testCase(Tester & t, int x = -1)  
  58. {  
  59.   t.begin(x);  
  60.   for(int i = 1; i <= 1000; ++i){ // for each bottle  
  61.     for(int x = i, n = 0; x; x >>= 1, ++n){ // each bit  
  62.       if(x & 1){  
  63.         t.feed(n, i);  
  64.       }  
  65.     }  
  66.   }  
  67.   
  68.   t.end();  
  69.   int id = 0;  
  70.   for(int i = 9; i >= 0; --i){  
  71.     id = (id << 1) | (t.query(i) ? 1 : 0);  
  72.   }  
  73.   
  74.   t.judge(id);  
  75. }  
  76.   
  77. int main()  
  78. {  
  79.   Tester t;  
  80.   
  81.   // cover  
  82.   for(int x = 0; x < 1001; ++x){  
  83.     testCase(t, x);  
  84.   }  
  85.   
  86.   // random test  
  87.   for(int x = 0; x < 100; ++x){  
  88.     testCase(t);  
  89.   }  
  90.   
  91.   cout << "passed" << endl;  
  92.   
  93.   return 0;  
  94. }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章