汉诺塔问题
给定一个由n个圆盘组成的塔,这些圆盘按照大小递减的方式套在第一根桩柱上。现要将整个塔移动到另一根桩柱上,每次只能移动一个圆盘,且较大的圆盘在移动过程中不能放置在较小的圆盘上面。
输入格式:
输入由四行: 第一行是圆盘数量n(1<=n<=10); 第二行到第四行分别是三根桩柱的名字(字符串),n个盘子套在第一根桩柱上。
输出格式:
输出移动步骤,每行输出一步。
输入样例:
在这里给出一组输入。例如:
2
a
b
c
输出样例:
在这里给出相应的输出。例如:
a->b
a->c
b->c
分析,假设现在有三个柱子,分别为S、T、D,分别表示为原始柱子(即待移动盘子的柱子),T是临时柱子,表示S柱子上的一些盘子得借助T柱子才能移动到D柱子。D是目标柱子。现在怎么把S柱子上的所有盘子移动到D柱子,并且D柱子从底到上的盘子是从大到小的???
假设只有一个盘子,很简单,直接从S柱移动到D柱子,我们记为S->D,那如果是2个盘子,先把S柱子上面那个盘子放在T柱子上,即S->T,然后把S柱子下面那个盘子放在D柱子上,即S->D,最后把T柱子上的那个盘子放到D柱子即可,即T->D。现在如果是n个盘子呢??细心的同学已经发现了这是一个递归问题,可以先把n-1个盘子借助D柱子移动到T柱子,然后把S柱子最底下那个盘子移动到D柱子,然后再把n-1个柱子,借助S柱子移动到D柱。
代码如下:
void Han_nuo1(int n,char S, char T, char D)//S表示原始柱子,即一开始就有很多盘子待移动的柱子
//T表示S柱子借助T柱子到达D柱子,T是临时柱子,D表示目标柱子
{
if (n == 1)//当只有一个盘子时,直接把盘子从S柱移动到D柱
{
printf("%c->%c\n",S,D);
}
else
{
Han_nuo1(n-1,S, D, T);//先把n-1个盘子借助D柱子移动到T柱
printf("%c->%c\n",S,D);//再把剩下的一个盘子移动到D柱
Han_nuo1(n-1,T, S, D);//最后把剩下的n-1个盘子借助S柱移动到D柱
}
}
int main()
{
char S='S', T = 'T', D = 'D';
int n = 0;
printf("输入S柱子上有几个盘子:\n");
scanf("%d", &n);
int* count=&n;
Han_nuo1(n,S, T, D);
system("pause");
return 0;
}
运行结果:
当盘子大于20个时,会发现要移动的次数非常大,现在下面给出能计算移动次数的版本,假设每一动一个盘子就记为移动一次,不管是移动到哪个柱子上。
汉诺塔加强版如下:
void Han_nuo2(int n, char S, char T, char D, int* count)//S表示原始柱子,即一开始就有很多盘子待移动的柱子
//T表示S柱子借助T柱子到达D柱子,T是临时柱子,D表示目标柱子,count记录移动的次数
{
if (n == 1)
{
printf("%c->%c\n", S, D);
(*count)++;
}
else
{
Han_nuo2(n - 1, S, D, T, count);
printf("%c->%c\n", S, D);
(*count)++;
Han_nuo2(n - 1, T, S, D, count);
}
}
int main()
{
char S = 'S', T = 'T', D = 'D';
int n = 0;
printf("输入S柱子上有几个盘子:\n");
scanf("%d", &n);
int count=0;
Han_nuo2(n, S, T, D, &count);
printf("%d\n", count);
system("pause");
return 0;
}
运行结果:
想必已经发现规律了,S柱子上要移动N盘子,移动的次数为2^N-1次,当盘子大于30个时,移动的次数是非常大的。