汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
一、问题的分解
当 n = 1 时:
n=1时,只需把圆盘从A转移到C即可
当 n != 1 时:
第一步,将圆柱A上n-1个通过C转移到B上
第二步,将圆柱A上的第n个转移到C上
第三步,将圆柱B上的n-1个通过A转移到C上
二、代码的实现
#include <stdio.h>
int count;
void move(char A, char C, int n)
{
printf("把第%d个圆盘从%c->%c\n", n, A, C);
count++;
}
void Hanno(char A, char B, char C, int n)
{
if (n == 1)
{
move(A, C, n);
}
else
{
//将n-1个圆盘从A柱借助于C柱移动到B柱上
Hanno(A, C, B, n - 1);
//将A柱子最后一个圆盘移动到C柱上
move(A, C, n);
//将n-1个圆盘从B柱借助于A柱移动到C柱上
Hanno(B, A, C, n - 1);
}
}
int main()
{
int n = 0;
printf("输入A柱子上的圆盘个数:");
scanf("%d", &n);
//将n个圆盘从A柱借助于B柱移动到C柱上
Hanno('A', 'B', 'C', n);
printf("一共移动了%d次圆盘", count);
return 0;
}
三、谈一谈自己的理解
我觉得思想的理解其实并不难,简单来说可以理解为:
问:怎么把4个盘子从A移动到C?
答:把上面的3个盘子移动到B,把最下面的第4个移动到C,然后把上面的3个移动到C。
问:那怎么把上面的3个盘子移动到B?
答:把上面的2个盘子移动到C,把第3个移动到B,然后把上面2个移动到B。
问:那怎么把上面2个盘子移动到C?
答:把最上面的1个移动到B,把第2个移动到C,然后把最上面的1个移动到C。
问:那怎么把最上面的移动到B?
答:当移动1个盘子的时候,直接移动。
引用自B站用户“金乘弍”的评论,我觉得说的十分的有道理
难点在于对代码的理解
关键的代码是这一段
void Hanno(char A, char B, char C, int n)
{
if (n == 1)
{
move(A, C, n);
}
else
{
//将n-1个圆盘从A柱借助于C柱移动到B柱上
Hanno(A, C, B, n - 1);
//将A柱子最后一个圆盘移动到C柱上
move(A, C, n);
//将n-1个圆盘从B柱借助于A柱移动到C柱上
Hanno(B, A, C, n - 1);
}
}
就我个人理解,主函数中调用Hanno函数中的A、B、C为实参,代表的是ABC三根柱子,
函数定义中的A、B、C为形参,分别代表了起始柱、过渡柱、目标柱,而在函数递归的过程中A、B、C三个柱子的身份是在相互变化的,下面我大概写了一下传参的过程(假设n=3的情况下):
四、总结
写这篇文章的主要目的是为了帮助自己梳理一下汉诺塔问题的逻辑,若是能帮助到其他人那就更好了,梳理完逻辑思路不禁还是感叹这种想法的奇妙,虽然已经大概理解了汉诺塔问题的解决思路,但也只能是跟在别人的步伐后边罢了,想要能够自己解决类似的问题还差的很远。
文章中内容若是有什么不对的地方,还请各位大佬指正