漢諾塔問題是大家理解遞歸的一個基礎問題。看了很多博客都不是很理解,下面我將從最簡單的解法爲大家講解:
1.首先是一個盤子,即A塔上有1個盤子的情況(Emmm,畫圖水平有限,僅限說明問題);
這是我們只需要將A中的盤子移到C中,經過一次操作即可:The 1:{A}-->{C}
2.兩個盤子的情況:
只需要進行如上三步就可以:
The 1:{A}-->{B} The 2:{A}-->{C} The 3:{B}-->{C}
從這三步我們可以看出,我們這裏將B作爲一個緩衝柱來看待。先將小盤移到B,再將大盤移到C,然後再把小盤移到C。
3.兩個盤子可能還是發現不了規律,我們再推廣成三個盤子看一下:
通過以上七步,我們可以驗證A中有兩個盤子的結論,我們不斷地將A柱和B柱當成緩衝柱。將所有盤子移動到C柱上。
在這裏,我們思考一下:
解決三個盤子的問題可不可以看成解決兩個盤子的問題呢?
我們把三個盤子的上邊兩個小盤子看成一個盤子。
然後我們要如何處理呢?
這樣是不是就變成了兩個盤子的移動。
當N變成64,也就是初始A柱上有64個盤子時,我們把前63個盤子看成一個整體移動到B,然後把第64個最大的盤子移動到C,最後再把B柱上的63個盤子看成一個整體移動到C盤上。這就相當於把64個盤子的規模轉化成了63個盤子。
那麼63個盤子要如何移動呢?
我們把前62個盤子看成一個整體,把前62個盤子從A柱移動到B柱,然後再把第63個大盤子從A柱移動到C柱,最後將B柱上的62個盤子堪稱一個 整體移動到C柱上,就完成了63個盤子的移動。
以此類推:
我們會發現問題規模會不斷的縮小。直到1個盤子的情況。
例如。N初始值爲3,即A上有三個盤子:
通過我們的遞推求解,要想解決三個盤子的情況,先解決 n-1即2個盤子的情況。
要想解決兩個盤子的情況要先解決n-1即1個盤子的情況。
我們把一個盤子從A移動到C後,遞歸回溯,再把第二個盤子從A移動到B,最後把C上的盤子移動到B上,這樣兩個盤子的情況解決完,接着解決三個盤子的情況,把最後最大的盤子移動到C,然後把B中的最小盤子移動到A,然後把B中的第二個盤子移動到C,最後把A中的最小盤子移動到C,就成功解決了問題。
最後貼一下代碼:
#include<iostream>
using namespace std;
int i=0;
//n:A中初始的盤子數量
//a:A柱的名稱
//b:B柱的名稱
//c:C柱的名稱
int hannuota(int n,char a,char b,char c)
{
if(n==1)
{
i++;
printf("The %d:{%c}-->{%c}\n",i,a,c);//如果只有一個盤子就直接從A移動到C
}
else
{
hannuota(n-1,a,c,b);//把n-1個盤子看成一個整體從A移動到B
hannuota(1,a,b,c); //最大的一個盤子移動到C
hannuota(n-1,b,a,c);//最後把B中的n-1個盤子看成一個整體移動到B
}
}
int main()
{
hannuota(3,'a','b','c');
return 0;
}
代碼完全按照以上分析的思想進行撰寫。
有同學可能對遞歸不太瞭解,這裏以N=3對遞歸進行分析,如圖:
感覺大家觀看,有什麼寫的不好的不對的地方請留言給出。謝謝。嘿嘿。