遞歸算法9——複雜遞歸之漢諾塔問題

 

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

【分析】
這個問題其實就是將n個圓盤從柱子A上移動到柱子C上,在移動過程中可以利用柱子B,每次只能移動一個圓盤,且始終保持大圓盤在下,小圓盤在上。

要把這n個圓盤從柱子A中藉助柱子B移動到C中,要先把上面的n-1個盤子從柱子A中藉助柱子C移動到B中,然後把第n個圓盤直接移動到柱子C上面,之後再把n-1個圓盤從柱子B藉助柱子A移動到C中,這樣就把n的問題分解爲n-1的問題。

這樣即可實現將n個盤子從柱子A移動到柱子C上,但是還有一個問題沒有解決,就是怎樣才能將n-1個圓盤從A移動到B上,然後再從柱子B移動到柱子C上。

要把n-1個圓盤從柱子A上柱子B上,需要吸納將上面的n-2個盤子藉助B從柱子A移動到柱子C上,然後將第n-1個圓盤直接移動到B上,之後再借助A將n-2個圓盤從C移動到B上。

要將n-1個圓盤從柱子B移動到柱子C還是要藉助遞歸實現。移動圓盤的過程正好符合遞歸的特點,將較大的問題簡化爲規模較小的問題,遞歸結束的條件就是一次只需要移動一個盤子,否則遞歸將繼續進行下去。

爲了使問題簡化,我們分析一下將3個圓盤從柱子A藉助B移動到C上的過程。

(1)將柱子A上的兩個圓盤移動到柱子B上(藉助柱子C)。
(2)將柱子A上的一個圓盤直接移動到柱子C上(A->C)。
(3)將柱子B上的兩個圓盤移動到柱子C上(藉助柱子A)。

其中步驟(2)可以直接實現,第(1)步可以繼續分解。

a.將柱子A上的一個圓盤直接移動到柱子C上(A->C)。
b.將柱子A上的一個圓盤直接移動到柱子B上(A->B)。
c.將柱子C上的一個圓盤直接移動到柱子B上(C->B)。

第(3)步可以繼續分解:

a.將柱子B上的一個圓盤直接移動到柱子A上(B->A)。
b.將柱子B上的一個圓盤直接移動到柱子C上(B->C)。
c.將柱子A上的一個圓盤直接移動到柱子C上(A->C)。

A->C,A->B,C->B,B->A,B->C,A->C

code:

#include<stdio.h>
#include <iostream>
void hanoi(int n, char one, char two, char three);
void move(char x, char y);
void main()
{
	int n;
	printf("請輸入圓盤的個數:");
	scanf("%d", &n);
	printf("移動步驟如下:\n");
	hanoi(n, 'A', 'B', 'C');
	system("pause");
}
void move(char x, char y)
{
	printf("%c-->%c\n", x, y);
}
void hanoi(int n, char one, char two, char three)
{
	if (n == 1)
		move(one, three);
	else
	{
		hanoi(n - 1, one, three, two);
		move(one, three);
		hanoi(n - 1, two, one, three);
	}
}


結果:

 

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