Description
(n階Hanoi塔問題)假設有三個分別命名爲A、B、C的塔座,在塔座A上插有n(n<20)個直徑大小各不相同、依小到大編號爲1,2,…,n的圓盤。現要求將A軸上的n個圓盤移至塔座C上並仍按同樣順序疊排,圓盤移動時必須遵循下列規則: 1)每次只能移動一個圓盤; 2)圓盤可以插在A、B、C中的任一塔座上; 3)任何時刻都不能將一個較大的圓盤壓在較小的圓盤之上。 請通過編程來打印出移動的步驟.
Input
只有一組輸入數據.輸入數據N(;表示在開始時A塔座上的盤子數),當輸入0時程序結束.
Output
輸出移動的步驟.如"A-->C","A-->B"等.每兩的步驟之間有三個空格隔開,每輸出5個步驟就換行.詳細的見Sample Output.
Sample Input
5
2
0
Sample Output
A-->C A-->B C-->B A-->C B-->A
B-->C A-->C A-->B C-->B C-->A
B-->A C-->B A-->C A-->B C-->B
A-->C B-->A B-->C A-->C B-->A
C-->B C-->A B-->A B-->C A-->C
A-->B C-->B A-->C B-->A B-->C
A-->C
A-->B A-->C B-->C
Hint
注意:此題每一行最後有3個空格
首先說一下,題目上的輸出亂了,我直接複製的沒有改,>應該是>
漢諾塔問題是個很經典的遞歸問題,但也比較難理解。
解題的方法大致是:移動當前n階漢諾塔的最大一個盤子到目的柱子疊起來,將n階漢諾塔變成n-1級漢諾塔,然後重複挪n-1箇中最大的盤子到目的柱子,直到挪成一階漢諾塔
先寫一下核心的解法
void move(int n,char x,char y,char z)
{
if (n == 1)
{
printf("%c-->%c ", x, z);
return;
}
move(n-1,x,z,y);
printf("%c-->%c ",x, z);
move(n-1,y,x,z);
}
下面是ac代碼及詳解:
#include<stdio.h>
int vis;//這個參數和算法無關,只是爲了標記,滿足題目的五步一換行,否則題目會PE
int main()
{
int n;
void move(int n, char x, char y, char z);//******此函數的作用是將x柱子上的n個盤子移動到z柱子上,同時輸出要經歷的步驟
while (~scanf("%d",&n) && n)
{
vis=1;
move(n, 'A', 'B', 'C');//函數的直接目的,將A柱上的盤子移到C柱,同時輸出步驟
if ((--vis % 5))printf("\n");//如果最後一位剛好是第五個
}
return 0;
}
void move(int n,char x,char y,char z)//x爲初始塔,y表示藉助塔,z表示目標塔。
{
//******此函數的作用是將x柱子上的n個盤子移動到z柱子上,同時輸出要經歷的步驟,x上面的盤子始終是由小到大
//x表示當前要移動的盤子所在的柱子,n表示當前有多少個盤子在x上,y表示藉助y柱子,z表示需要把x上的n個盤子移動到z柱子上。
if (n == 1)//n=1時,x上只剩一個盤子的時候,直接移動到z
{
printf("%c-->%c ", x, z);
if (!(vis++ % 5))printf("\n");
return;
}
//n>1時,x上還有n個盤子的時候,當前目的就是把上面的n-1個盤子全挪到y上,這樣就可以把當前最大的那個盤子挪到z上
//怎麼挪呢?
move(n-1,x,z,y);//首先請看上面注了六個*號的那句話。
//不管這步的函數內部是怎麼運行的,總之,這個函數的運行後的效果是將x柱子上的n-1個盤子移動到y柱子上
printf("%c-->%c ",x, z);//移動x上的盤子到z上,ps:雖然沒有挪動這個操作,但挪動到目標位置後就不用管了,變成了n-1階漢諾塔,所以直接無視掉它
if (!(vis++ % 5))printf("\n");//五個一換行
//關鍵是要知道每步的作用是什麼,不用去想它是怎麼做到的
//現在我們的目的就變成了將y上的n-1個盤子移動到z上
move(n-1,y,x,z);//接下來我們只需要解決n-1階漢諾塔了,也就是這個函數的目的,將y上剩餘的n-1個盤子移動到z柱子上
}
成在堅持,貴在堅持,難在堅持!