汉诺塔问题

来源:互联网 发布:软件设计师招聘 编辑:程序博客网 时间:2024/06/06 02:07

汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
这里写图片描述

现在要求通过编程输出移动盘子的步骤。
解题思路:要把64个盘子从A移动到C,显然不能是一部完成的,我们需要找到一个思路,把问题简化。按照递归的思想:我们找很多人来帮忙,每个人有自己的任务,我是第一个人,分工如下:
1.让第二个人把63个盘子移动到B;
2.我自己把最后一个盘子从A移动到C;
3.让第二个人把B上的63个盘子从B移动到C。
可以看到第一步与第三步的操作是类似的,只是移动的位置不同,而其中第一步又可以划分成下面三步:
1.让第三个人把62个盘子从A移动到C;(注意这里的最终目的是实现上面过程的第一步,即把63个盘子从A移动到B,所以第一步是先把62个盘子移动到C)
2.第二个人把最后一个盘子(第63个)从A移动到B;
3.第三个人把62个盘子从C移动到B。
上述的第一步又可以拆分成以下三步:
1.让第四个人把61个盘子从A移动到B;
2.第三个人把最后一个盘子从A移动到C;
3.第四个人把61个盘子从B移动到C;
依次类推……如此层层下方,知道后来第63个人,他的任务是,将2个盘子从一个座位移动到另一个作为,至此全部工作都已落实,都是可以执行的。
应当说明的是,只有第64个人的任务完成以后,第63个人的工作才能完成。只有第2-64个人的工作完成以后,第一个人(我)的工作才能完成。这是一个经典的递归的问题。
为了便于理解,我们先分析将三个盘子从A移动到C的过程,移动的示意图是这样的:
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

要注意,图中的第一步将两个盘子从A移动到C又可用递归方法分解为:
1.将A上的一个盘子从A移动到C;
2.将A上的一个盘子从A移动到B;
3.将C上的一个盘子从C移动到B。
同理图中的第三步也要分解为:
1.将B上的一个盘子从B移动到A;
2.将B上的一个盘子从B移动到C;
3.将A上的一个盘子从A移动到C。
以上综合起来可以得到移动3个盘子的步骤为:
A->C,A->B,C->B,A->C,B->A,B->C,A->C共经历(2的三次方-1)=7步。
由上面的分析知道,将n个盘子从A移动到C可以分解为一下三个步骤:

  1. 将A上n-1个盘子从借助C移动到B;
  2. 将A剩下的一个盘子移动到C上;
  3. 将n-1个盘子 从B座借助A座移动到C座。
    由于上面的第一和第三步,都是从一个座借助一个座移动到另一个座,第二步可以一步实现,所以将上面的操作分成两类:
  4. 将n-1个盘子从一处移到另一处;
  5. 将一个盘子从一处移到另一处。
    编写程序
    分别用两个函数实现上述的两种操作,用hanoi函数实现上面的第一类操作,用move函数实现上面的第二类操作。
#include "hanoi.h"int main(){    int m;    printf("请输入A中盘子数");    scanf("%d",&m);    printf("将A中%d个盘子移动到C的步骤为:\n",m);    hanoi(m,'A','B','C');    return 0;}
#ifndef HANOI_H_INCLUDED#define HANOI_H_INCLUDED#include <stdio.h>#include <stdlib.h>void hanoi(int n,char a,char b,char c);void moveItem(char a,char b);int cnt=0;//用于记录次数void moveItem(char a,char b){    printf("第%d次操作:",++cnt);    printf("%c->%c\n",a,b);}void hanoi(int n,char a,char b,char c){    if(n==1) moveItem(a,c);    else{        hanoi(n-1,a,c,b);        moveItem(a,c);        hanoi(n-1,b,a,c);    }}#endif // HANOI_H_INCLUDED

运行结果:这里写图片描述

Tips:假如每秒钟进行一次操作,共需多长时间呢?
一个平年365天有31536000 秒,闰年366天有31622400秒,平均每年31556952秒,计算一下:
18446744073709551615秒
这表明移完这些金片需要5845.54亿年以上,而地球存在至今不过45亿年,太阳系的预期寿命据说也就是数百亿年。真的过了5845.54亿年,不说太阳系和银河系,至少地球上的一切生命,连同梵塔、庙宇等,都早已经灰飞烟灭。
所以有预言说,这件事完成时宇宙会在一瞬间闪电式毁灭。但愿没人会完成这个成就~

原创粉丝点击