【问题描述】
汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
【问题分析】
汉诺塔用递归理解较为简单,在理解时,不要局限常规,最好把三根柱子围成一个正三角形理解,因为在递归运算中,辅助的柱子不是固定不变的。标明1(start)、2(temporary)、3(goal)号,假设要把n个圆盘从1号移到3号。按平常来理解,先把上面的n-1个圆盘按照一定方法借助3(goal)号柱子全部移到2(temporary)上(这个方法是什么不用管,先假设它存在直接用就对了),再把1(start)号中剩的一个最大的直接移动到3(goal)上。此时要突破思维定式,把2号当开始柱子,1号当临时柱子,3号仍为目标柱子。即变成把n-1个圆盘从2借助1移动到3的问题的,方法还是之前的方法,即递归调用该方法即可。是递归就应该有终止条件,很明显,该函数终止条件是圆盘的参数减到1时。
【解决方法】
#include<iostream>
using namespace std;
void hanoi(int disc, int start = 1, int temporary = 2, int goal = 3)
{
if (disc == 1)//递归终止条件
printf("%d -> %d\n", start, goal);//可直观看出圆盘的移动
else
{
hanoi(disc - 1, start, goal, temporary);//除了1号中最大的圆盘,其他的圆盘借助函数和3号柱子移动到2号上
hanoi(1, start, temporary, goal);//将上面剩下那个最大的直接移动到3号柱子上
hanoi(disc - 1, temporary, start, goal);//借助1号柱子和函数将2号中刚移动过来的圆盘全部移动到3号上
}
}
int main()
{
int disc;
cout << "请输入计算规模:";
cin >> disc;
hanoi(disc);
}
【温馨提示】
在解决递归问题时一定不要陷进去,一定要跳出来进行考虑。在递归前,要考虑好所有终止条件,以及递归中是否会出现不同于原始状态的情况,如果有的话可能要更改参数位置或其他来连续递归(就比如这个汉诺塔,else中三次调用),没有的话就调用一次即可(比如斐波那契数列)。