經典算法詳解(1): 河內之塔

說明:

河內之塔(Towers of Hanoi)是法國人M.Claus(Lucas)於1883年從泰國帶至法國的,河內爲越戰時北越的首都,即現在的胡志明市;1883年法國數學家 Edouard Lucas曾提及這個故事,據說創世紀時Benares有一座波羅教塔,是由三支鑽石棒(Pag)所支撐,開始時神在第一根棒上放置64個由上至下依由小至大排列的金盤(Disc),並命令僧侶將所有的金盤從第一根石棒移至第三根石棒,且搬運過程中遵守大盤子在小盤子之下的原則,若每日僅搬一個盤子,則當盤子全數搬運完畢之時,此塔將毀損,而也就是世界末日來臨之時。

分析:

假設三根石柱分別爲A,B,C,目標是將A石柱上的64個金盤移到C石柱上。可以這樣分析,如果A石柱只有一個盤子,則直接A -> C(由A移到C)。如果A石柱有兩個盤子,則現需要這樣移動:A -> B , A -> C ,B -> C。那如果是三個盤子呢?這時就很難想象出該如何移動了。但是三個盤子的移動可以分解成三個大步驟: 

(1)將前兩個盤子由A -> B(將C作爲輔助);
(2)在將A中最後的一個盤子直接由A -> C,此時A石柱就空了,B石柱放置了兩個金盤,C石柱放置了一個最大的金盤;
(3)最後只需要藉助空柱子A,將B石柱的兩個盤子由 B -> C(將A作爲輔助)。

這樣分析,就可以發現河內之塔是個遞歸問題。將n個盤子由A -> C(藉助B)可以分解爲三個步驟: 將前n-1個盤子由A -> B(藉助C),將第n個盤子直接由 A -> C,將B石柱的n-1個盤子由B -> C(藉助A)。

實現:

/****************************************************************
 Name: HanoiTowers.c
 Description: the problem is a classical recursion problem
 Author: [email protected]
 Time: 2014-9-10
****************************************************************/ 

#include <stdio.h>

void MoveTowers(int n,char begin,char middle,char end)
{
	if(1==n)
	{
		printf("%c -> %c\n",begin,end);
		return;
	}
	MoveTowers(n-1,begin,end,middle);
	printf("%c -> %c\n",begin,end);
	MoveTowers(n-1,middle,begin,end);
} 

int main()
{
	int nDisks;
	printf("please input the disks:\n");
	scanf("%d",&nDisks);
	MoveTowers(nDisks,'A','B','C');
	return  0;
}

總結:

河內之塔是個典型的遞歸求解問題,只要認真分析,就能發現這個問題存在子結構。 



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