算法笔记 —— 汉诺塔详解

一.问题来源

相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号X、Y、Z),在X杆自下而上、由大到小按顺序放置64个金盘。游戏的目标:把X杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于X、Y、Z任一杆上。

二.小游戏体验

以三个为例,移动方法如下(小游戏网址:汉诺塔小游戏
在这里插入图片描述

三.思路分析

以最简单的例子分析,当我们想把3个金盘从X杆移动到Z杆上时,可以想象,先通过Z,将除了最大金盘以外的所有金盘移动到Y杆上,再将最大(最底下)的金盘移动到Z杆上,再通过X杆,将Y杆上的所有金盘移动到Z杆上:

  1. 通过Z杆,将2个金盘移动到Y杆:

在这里插入图片描述

  1. 将最大的金盘移动到Z上:

在这里插入图片描述

  1. 借助X,将Y杆上的金盘移动到Z上:
    在这里插入图片描述
    所以,当有4个金盘时,可以将前3个金盘先移动到Y,再将最大的金盘移动到Z,再将Y上金盘移动到Z,而这3个金盘的移动可以依照前面的分析,而5个金盘则可以看成先移动前4个,以此类推,这便是递归的思想

也就是说,当有64个金盘时,我们其实要解决两个问题:

  1. 将X上的63个金盘通过Z移动到Y
  2. 将Y上的63个金盘通过X移动到Z

这时,将问题1问题2分别处理:
问题1将X上的63个金盘通过Z移动到Y分解为:

  1. 先将前62个盘子移动到Z上,确保大盘在下,小盘在上
  2. 再将最底下的第63个盘子移动到Y上
  3. 最后将Z上的62个盘子移动到Y上

问题2将Y上的63个金盘通过X移动到Z分解为:

  1. 先将62个盘子移动到X上
  2. 再将最底下的第63个盘子移动到Z上
  3. 最后将X上的62个盘子移动到Y上

依次递归便可以完成任务。

四. 程序实现

#include <stdio.h>
#include <getopt.h>

void move(int n,char x,char y,char z)  //将n个盘子从x借助y移动到z
{                                                       
    if(1 == n)                            
    {                                     
        printf("%c-->%c\n",x,z);          
    }                                     
    else                                  
    {                                     
        move(n-1,x,z,y);  //将n-1个盘子从x借助z移动到y
        printf("%c-->%c\n",x,z);  //将第n个盘子从x移动到z
        move(n-1,y,x,z);  //将n-1个盘子从y借助x移动到z
    }                                         
}      

int main(int argc,char **argv)
{
    int    ch;
    int    num;

    struct option                 opts[] = {
            {"number",required_argument,NULL,'n'},
            {NULL,0,NULL,0}
        };

    while((ch = getopt_long(argc,argv,"n:",opts,NULL)) != -1)  //通过命令行传参指定金盘个数
    {
        switch(ch)
        {
            case 'n':
                num = atoi(optarg);
                break;

            default:
                break;

        }
    }

    printf("移动步骤如下:\n");
    move(num,'X','Y','Z');

    return 0;
}

运行程序:
在这里插入图片描述
通过 -n 指定金盘数量,当有3个金盘时,操作如图,对比前面的动图,操作正确。
在这里插入图片描述
在这里插入图片描述
这便是经典的汉诺塔问题,在理解这个问题的解决方法上花了很大的功夫,然而代码实现却如此简单,这也许就是算法与程序结合所带来的魅力吧!
古印度僧侣曾预言,当圣庙中的金盘全部从3根针中的一根全部(64)移动到另外两根中的一根时,世界将会迎来灭亡…

猜你喜欢

转载自blog.csdn.net/weixin_45121946/article/details/106883755