“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. }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章