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柱子上
}
成在坚持,贵在坚持,难在坚持!