算法篇——漢諾塔

1.研究背景

    漢諾塔:漢諾塔(又稱河內塔)問題是源於印度一個古老傳說的益智玩具。
	大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞着64片黃金圓盤。
	大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。並且規定,在小圓盤上不能放大圓盤,
	在三根柱子之間一次只能移動一個圓盤。

法國數學家愛德華·盧卡斯曾編寫過一個印度的古老傳說:在世界中心貝拿勒斯(在印度北部)的聖廟裏,一塊黃銅板上插着三根寶石針。印度教的主神梵天在創造世界的時候,在其中一根針上從下到上地穿好了由大到小的64片金片,這就是所謂的漢諾塔。不論白天黑夜,總有一個僧侶在按照下面的法則移動這些金片:一次只移動一片,不管在哪根針上,小片必須在大片上面。僧侶們預言,當所有的金片都從梵天穿好的那根針上移到另外一根針上時,世界就將在一聲霹靂中消滅,而梵塔、廟宇和衆生也都將同歸於盡。 [2]

不管這個傳說的可信度有多大,如果考慮一下把64片金片,由一根針上移到另一根針上,並且始終保持上小下大的順序。這需要多少次移動呢?這裏需要遞歸的方法。假設有n片,移動次數是f(n).顯然f(1)=1,f(2)=3,f(3)=7,且f(k+1)=2*f(k)+1。此後不難證明f(n)=2^n-1。n=64時,假如每秒鐘一次,共需多長時間呢?一個平年365天有31536000 秒,閏年366天有31622400秒,平均每年31556952秒,計算一下:18446744073709551615秒
這表明移完這些金片需要5845.54億年以上,而地球存在至今不過45億年,太陽系的預期壽命據說也就是數百億年。真的過了5845.54億年,不說太陽系和銀河系,至少地球上的一切生命,連同梵塔、廟宇等,都早已經灰飛煙滅。

2.研究內容

有三根杆子A,B,C。A杆上有N個(N>1)穿孔圓環,盤的尺寸由下到上依次變小。要求按下列規則將所有圓盤移至C杆:

1.每次只能移動一個圓盤;
2.大盤不能疊在小盤上面。

提示:可將圓盤臨時置於B杆,也可將從A杆移出的圓盤重新移回A杆,但都必須遵循上述兩條規則。

問:如何移?最少要移動多少次?

3.代碼實現

爲了解決這個問題,不妨假設已經知道怎樣移動N-1個圓環了。現在,爲了把起點盤上的圓環移動到目標盤,需要做如下操作:

1、把N-1個圓環從起點盤移動到(當前)沒有任何圓環的過度盤;

2、把最後一個圓環從起點盤移動到目標盤;

3、把N-1個圓環從國度盤移動到目標盤(模仿1和2的操作方法來實現)。

Gif動態圖片
在這裏插入圖片描述

C++實現漢諾塔算法的程序:

#include <iostream>
#include <cstdio>

using namespace std;
 
void hannoi (int n, char A, char B, char C)  // 把A盤裏面的圓圈轉移到C盤裏面【A--C】。
{
    if (n == 1)
    {
        cout << "移動圓圈" << n << "從盤" << A << "盤" << C << endl;  //把最後一個圓環從起點盤移動到目標盤。
    }
    else
    {
        hannoi (n-1, A, C, B);  // 把N-1個圓環從起點盤移動到(當前)沒有任何圓環的過度盤;通過B、C盤在此函數調用中調用位置的互換,來實現把N-1個圓環從A盤到B盤的轉移【A--B】。
        cout << "移動圓圈" << n << "從盤" << A << "盤" << C << endl;
        hannoi (n-1, B, A, C);  // 把N-1個圓環從國度盤移動到目標盤(模仿1和2的操作方法來實現);通過A、B盤在此函數調用中位置的互換,來實現N-1個圓環從B盤到C盤的轉移【B--C】。
    }
}
 
int main()
{
    int n;
    cin >> n;

    hannoi (n, 'a', 'b', 'c');

    system("pause");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章