狐狸捉兔子問題


1. 問題描述

圍繞着山頂有10個洞,狐狸想要吃兔子,兔子說:“可以,但必須找到我,我就藏身於這10個洞中,你從10號洞出發,先到1號洞找,第二次隔1個洞找,第三次隔2個洞找,以后如此類推,次數不限。”但狐狸從早到晚進進出出了1000次,仍沒有找到兔子。問兔子究竟藏在哪個洞里?

2. 問題分析

(1) 把10個洞編上序號:1,2,3,4,5,6,7,8,9,0
(2) 狐狸從0號洞出發,第1次在1號洞找;第2次隔1個洞,在3號洞找;第3次隔2個洞,在6號洞找;第4次隔3個洞,在0號洞找;第5次隔4個洞口,即在5號洞找;以此類推。
(3) 可見,其實上述問題其實是一個等差數列求和問題(首項為1,公差為1)。將求和結果對10取余(求和結果%10),即可得到狐狸每次進去的洞口號。
(4) 如下圖所示,仔細觀察可以發現,如果狐狸連續兩次都進入出發洞口(0號洞),表明接下來進入洞口的順序與之前的順序相同!因此遇到連續兩次都進入出發洞口的情況,即可停止尋找,因為接下來只是重復之前找過的洞口。

3. 算法描述

(1) 首項為1,公差為1的等差數列求和公式:n*(n+1)/2,n為尋找的次數
(2) 狐狸每次進入的洞口號為:(n*(n+1)/2)%10,對10取余是因為有10個洞口
(3) 設x為尋找的次數,連續兩次進入都是出發時的洞口(0號洞),可停止尋找。設 HOLENUM為洞口的個數,本例是10
     即第x-1次:((x-1)*(x-1+1)/2)%HOLENUM == 0
        第x次:(x*(x+1)/2)%HOLENUM == 0
     一般的,x = 2*HOLENUM。即如果洞口有10個,則需要找20次,就會在遇到連續兩次進入出發的洞口(本例是第19次和第20次)
     特殊的,如果HOLENUM是(2^k +1),則 x = HOLENUM,(k = 0,1,2,3......)。即如果洞口有15個, 則只需找15次,就會遇到連續兩次進入出發時的洞口(第14次和第15次)
(4) 可見,該算法的時間復雜度與洞口的個數有關,具體的時間復雜度為Θ(n)
 

4. 代碼實現

 1 #include <stdio.h>
 2 #define HOLENUM 10
 3 
 4 void FindRibbit(int Hole[HOLENUM]);
 5 
 6 int main()
 7 {
 8     int hole[HOLENUM] = {0};        // 10個山洞
 9     FindRibbit(hole);
10     return 0;
11 }
12 
13 void FindRibbit(int Hole[HOLENUM])
14 {
15     int i = 0;
16     int currenthole = 0, nexthole = 0;
17     for(i = 1; i <= 2 * HOLENUM; ++i)
18     {
19         currenthole = (currenthole + i) % HOLENUM;        // 當前進去的山洞
20         Hole[currenthole % HOLENUM] = 1;
21         nexthole = (currenthole + i + 1) % HOLENUM;        // 下一次進去的山洞
22         
23         if(currenthole == 0    && nexthole == 0)            // 如果連續兩次進去的山洞都是出發時的洞口,則接下來的進洞順序與前面的順序重復,故可以跳出循環
24             break;                                        // 本例是從10號(即0號)洞口出發
25     }
26     
28     for(i = 0; i < HOLENUM; ++i)                        // 輸出兔子可能躲藏的洞口
29     {
30         if(Hole[i] == 0)
31             printf("the ribbit may be in %d hole\n", i);
32     }
33 }

5. 測試結果

the ribbit may be in 2 hole
the ribbit may be in 4 hole
the ribbit may be in 7 hole
the ribbit may be in 9 hole

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM