200105 - n层汉诺塔问题
汉诺塔是一个古老的游戏,也是学习递归程序设计的一个经典问题,这个问题非常有助于纠正“我想跟踪整个递归过程”这种思维,并且坚定“只要子问题操作过程相同,而我把这一过程设计的正确,那么递归程序会得到正确结果”的想法:
有3个柱子,分别记为:A,B,C;A上有n个圆盘,每次移动一个圆盘,最终把所有圆盘都移动到C柱,移动过程中只能拿走最上面的圆盘并放在比它大的圆盘上面,下面是一个三个圆盘的例子:
C柱是目标柱,B柱是临时存储柱。现在,来观察四个盘子的情况:
和三个盘子的情况对比:四个盘子的情况是先把前三个盘子从A柱移动到B柱而不是C柱,之后把第四个盘子从A柱移动到C柱,之后把前三个盘子从B柱移动到C柱。
那么,再增加一个盘子时应该如何移动呢?
对于汉诺塔问题的分析思路有一个有趣的比喻:把大象放在冰箱里需要几步?打开冰箱门——把大象放到冰箱里——关上冰箱门:
我们可以把最大的圆盘称为大象,那么打开冰箱门就是把上面n-1个圆盘移动到临时柱上;然后把大象塞到冰箱里——最大的圆盘放到目标柱上;最后关上冰箱门——把上面的n-1个圆盘从临时柱移动到目标柱上。
根据移动规则每次只能移动一个圆盘,所以我们在程序中只需描述从哪个柱拿到哪个柱即可,而关于小圆盘在大圆盘上的约定,我们只需要设计程序时保证大圆盘先被安放在目标柱或临时柱上——即达成了小圆盘在上的目的,思考:
1、如何把移动过程划分为相同操作的子过程?
2、处理子问题时,需要哪4个数据?(函数参数)
3、函数是否需要返回值?(返回值类型)
4、何时调用自己,何时达到递归边界?(函数内的处理逻辑)
输入
一行,一个正整数,表示汉诺塔的层数n。
对于100%的数据:
1\le n \le 10 。
输出
若干行,表示A柱起始,C柱结束的汉诺塔移动方案,每行格式为"From m to n"。
由于输出行数很多,建议使用printf来输出。
样例
输入
3
输出
From A to C From A to B From C to B From A to C From B to A From B to C From A to C
提示
可以搜到很多汉诺塔问题的解释,但想理解好汉诺塔问题,还是要“大处着眼”:把上面的n-1个小圆盘看做整体;“小处着手”:注意函数参数的意义(“开始位置”、“临时位置”、“目标位置”)不会由于传递的数值的变化而变化;某个参数进入函数时可能表示“临时位置”,但调用函数时我们把它填写在“目标位置”这个参数上,那么当被调用的函数运行时,它就代表了“目标位置”。