首页 > 代码库 > 经典算法详解(1): 河内之塔

经典算法详解(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: fuchencong@163.com
 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;
}

总结:

河内之塔是个典型的递归求解问题,只要认真分析,就能发现这个问题存在子结构。 



经典算法详解(1): 河内之塔