標籤:style class blog code http ext
漢諾塔,相信大家已經不再陌生。我覺得也可能是很多人比較迷茫的問題。今天,不知道怎麼突然靈光一現,把這個困擾我好久的問題給解決了。分享給大家,希望有所協助。
至於問題背景,這裡再大致介紹一下,
將一系列木塊,從A移動到C,可以藉助B,當然,木塊的秩序不能改變,即小的木塊一定要放在大的木塊上面。現在要怎麼做呢?
遞迴?沒錯!就是遞迴,那怎麼分析呢?
現在,可以這樣想:
①假設只有一個木塊,直接從A移動到C就可以了,問題完成。
②如果有n個木塊,那麼把A上面的n-1個木塊通過C移動到B上,A上面還剩下最大的一塊,直接移動到C上不就好了嗎?(
至於如何?n-1塊木塊的移動,具體細節可以先不考慮,這裡只是一種思想)
③現在的情況變成了B上還有n-1塊,A空了,需要把這n-1塊移動通過A移動到C上,看一下,這一個步驟是不是和②是相同的呢,只是參數相對發生了一下變化而已。這不就是遞迴的典型應用嗎,最後當只剩下一塊的時候就是遞迴出口。以三塊為例,下面是移動的圖解過程: 以上所講都是在圖解的方式下,理解起來應該不是太難。但問題畢竟要用程式來實現,現在我們換一種思路,用演算法來分析該問題:
/**n 移動的木塊個數a,b,c 中介木板*/hanoi(n,a,b,c)1 if n==1 then2 move(a,c)3 else4 hanoi(n-1,a,c,b)5 move(a,c)6 hanoi(n-1,b,a,c)
具體分析如下:
①代碼第一行的四個參數表示為,把a上的n個木塊通過b移動到c ②如果n為1,那麼直接從a移動到c即可,此為遞迴出口 ③當n不為1的時候,要先把a上面的n-1個木塊通過c移動到b ④再把a上面的一個移動到c ⑤最後把b上面的n-1個木塊通過a移動到c OK,問題至此解決! 當然,使用演算法講解時,只是一種思想,不能跟蹤到到每一次的具體實現。如果想跟蹤每一步的移動怎麼辦呢,於是我把代碼稍微改動了一下,使之每移動一次都顯示出來,完整如下:
#include<stdio.h>void move(char x,char y){ printf("%c-->%c\n",x,y);}void Hanoi(int n,char a,char b,char c){ if(n==1) move(a,c); else { Hanoi(n-1,a,c,b); move(a,c); Hanoi(n-1,b,a,c); }}int main(){ int N; printf("請輸入要移動的木塊數:"); scanf("%d",&N); Hanoi(N,‘A‘,‘B‘,‘C‘); return 0;}
經過這樣的一點小小改動之後,程式就能將每一步如何移動顯示出來了,也就達到了跟蹤觀察的目的。當然,如果有興趣的話,不妨自己手動追蹤一下,肯定會有不一樣的感受;
運行結果如下: 最後,經過我的幾組測試,貌似發現了一個有趣的結論:
採用漢諾塔移動木塊時,移動的次數是
2的n次方減1(2^n-1,其中n
為要移動的木塊數),如果有誤,懇請大家指點。 註:以上代碼均在 Code::Blocks + GNU gcc環境下編譯運行通過