遞迴的應用:求解漢諾塔問題
阿新 • • 發佈:2018-12-17
- 題目描述:漢諾塔問題是一個經典的問題,其來源據說在19世紀末歐洲的商店中出售一種智力玩具,在一塊銅板上有三根杆,最左邊的杆自上而下、由小到大順序串著64個圓盤構成的塔,遊戲的目的是將左邊A杆上的圓盤藉助最右邊的C杆,全部移動到中間的B杆上,條件是一次僅能移動一個盤,且不允許大盤放在小盤上面,問最少需要移動多少次。
- 解法描述:我們可知限制條件為:一次只能移動一個盤,且不允許大盤放在小盤上面。解法為:首先我們設要解決的漢諾塔有n個圓盤,對A杆上的全部n個圓盤從小到大順序編號,最小的為1號,依次遞增,最大的圓盤編號為n。
-
第一步:假設此時A杆上只有一個圓盤,即漢諾塔只有一層,那麼將其移動到B杆上即可。
-
第二步:對於有n(n>1)個圓盤的漢諾塔,將n個圓盤分為兩個部分,上面n-1個圓盤為一個部分,下面編號為n的一個圓盤為另一部分。
-
第三步:將“上面n-1個圓盤“看成一個整體,為了解決這n個圓盤的漢諾塔可以進行下列操作:
- 將A杆上的n-1個圓盤藉助B杆移到C杆上,此時設C杆上有n個盤子(n = n - 1);
- 將A杆上剩下的編號為n的盤子移動到B杆上;
- 將C杆上的n-1個盤子藉助A杆移到B杆上。
- 在將n-1個圓盤從C杆上移動到B杆上和原問題具有具有相同的特徵屬性,只是問題的規模小於原問題,故我們可以使用遞迴的方法來求解。
-
下面就以四個盤子為例,來解釋盤子的移動過程: 初始狀態的漢羅塔:
-
第一次藉助B杆將A杆上的n-1個盤子移動到C杆上並把A杆上的最後一個盤子移動打B杆上後的結果: 再借助B杆將C杆上的n-1個盤子移動到A杆並將C杆上的最後一個盤子移動到B杆上後的結果:
遞迴對A杆、B杆和C杆上的盤子的移動操作直至最後一個盤子移動到B杆上結束。
最後的結果:
程式設計實現:
#include<iostream> using namespace std; void Hanoi(int n, char a, char b, char c, int &count) { if(n == 1) { count++;//移動A杆上的最後一個盤子到B杆 } else { Hanoi(n - 1, a, b ,c, count); //A 杆藉助B杆移動n-1個盤子到C杆 count++; //移動A杆上的最後一個盤子到B杆 Hanoi(n - 1, c, b ,a, count); //C杆藉助B杆將n-1個盤子移動到A杆 } } int main() { int count,n; cout << "please input the count:"; cin >> n; count = 0; Hanoi(n, 'A', 'B', 'C', count); cout << "total = " << count << endl; }
測試結果: