【汉诺塔问题】,源于印度一个古老传说的益智玩具。大焚天创造世界的时候做了三根金刚石柱子,在一根柱子上按照从小到大的顺序摞放着64片圆盘。大焚天命令婆罗门把圆盘重新摆放在另一根柱子上,并且要求保持摆放顺序不变。游戏规则为:小盘子上不能摆放大盘子,每次只能移动一个盘子,可以借用中间柱子腾挪。
此问题可以抽象为这样的问题:
设有A、B、C三根柱子,A柱上有n个盘子,按从小到大的顺序整齐摆放,底下大,上面小。问在借助B柱腾挪的情况下,共需多少次移动,经过怎样的顺序,才可以把A柱上的全部盘子移动到C柱上,且保持摆放顺序不变?
先解决移动次数问题,采用数学归纳法。
当n=1时,1次(2^1-1);
当n=2时,3次(2^2-1);
当n=3时,7次(2^3-1);
当n=4时,15次(2^4-1);
以此类推,容易证明通项公式为:2^n-1次。
当n到了64次的时候,2^64-1将是一个巨大的天文数字。非人类所能完成。
解决此问题需要用到递归思想。将复杂问题分解成以下递归过程。
当n>2时,
1.将A柱上靠顶层的n-1个盘子通过C柱移动到B柱上(A->C->B);
2.将A柱上剩余的(也就是最底层的)那个盘子直接移动到C柱上(A->C);
3.将B柱上的n-1个盘子通过A柱移动到C柱上(B->A->C)。
当n=1时,
直接从A柱移动到C柱上(A->C)。
利用计算机的递归调用,这一复杂问题反而更简单了。详细解法见代码。运行结果见附图。
/*
*****************************************************
递归算法,解决汉诺塔问题
******************************************************
*/
#include <stdio.h>
int i=0; //i为全局移动次数累加器
void HannoiTower(int n,char a,char b,char c){//其中n为层数,a为起点,b为经过的中转点,c为目的地
if (n>=2){
HannoiTower(n-1,a,c,b);//把n-1个盘子从A柱经过C柱移动到B柱
printf("%d:%c-->%c\n",++i,a,c); //把A柱最底下的盘子移动到C柱
HannoiTower(n-1,b,a,c);//把B柱上的n-1个盘子经过A柱移动到C柱
}
else
{
printf("%d:%c-->%c\n",++i,a,c);
}
}
int main(){
int n;
printf("请输入汉诺塔层数:");
scanf("%d",&n);
HannoiTower(n,'A','B','C');
return 0;
}