• 用栈来求解汉诺塔问题


    【说明】:

      本文是左程云老师所著的《程序员面试代码指南》第一章中“用栈来实现汉诺塔问题”这一题目的C++栈方法的复现。

      本文只包含问题描述、C++代码的实现以及简单的思路,不包含解析说明,具体的问题解析请参考原书。

      感谢左程云老师的支持。

    【题目】:

      汉诺塔问题比较经典,这里修改一下游戏规则:现在限制不能从最左侧的塔直接移动到最右侧,也不能从最右侧直接移动到最左侧,而必须经过中间。求当有N层塔的时候,打印最优移动过程和最优移动总步数。

      例如,当塔为两层时,最上层的塔记录为1,最下层的塔记录为2,则打印:

      move 1 from left to mid

      move 1 from mid to right

      move 2 from left to mid

      move 1 from right to mid

      move 1 from mid to left

      move 2 from mid to right

      move 1 from left to mid

      move 1 from mid to right

      It will move 8 steps.

    【思路】:

      汉诺塔的第一个原则:不可以小压大;

      汉诺塔的第二个原则:若求最优解,不可后退。

    【编译环境】:

      CentOS6.7(x86_64)

      gcc 4.4.7

    【实现】:

      实现及测试代码:

    /*
     *文件名:limitHanoi.cpp
     *作者:
     *问题描述:限制汉诺塔移动方法,只能由左到中,由中到左,由中到右,由右到中,
     *          不可直接由左到右,由右到左。
     *          利用栈的结构求得最佳路径。
     *            下面是C++/stack实现代码。
     */
     
    #include <iostream>
    #include <stack>
    #include <stdlib.h>
    
    using namespace std;
    
    enum Action 
    { 
        No = 0, 
        LtoM = 1, 
        MtoL = -1, 
        RtoM = 2, 
        MtoR = -2 
    };
    
    /*
     *函数介绍:移动汉诺塔上的圆盘。
     *输入参数:record为上一个移动的步骤;now为即将移动的步骤;src为源栈;dst为目的栈。
     *输出参数:pre记录即将发生的移动步骤;src移动圆盘后的栈;dst移动圆盘后的栈。
     *返回值:若圆盘移动成功,则返回移动歩数1;若失败,则返回移动歩数0。
     */ 
    int moveDisc(Action &record,Action now,stack<int> &src,stack<int> &dst)
    {
        if(!src.empty() && (abs(record) != abs(now)) && (dst.empty() || src.top() < dst.top()) )
        {
            dst.push(src.top());
            src.pop();
            switch(now)
            {
                case 1:
                    cout << "Move " << dst.top() << " from left to mid;" << endl;
                    break;
                case -1:
                    cout << "Move " << dst.top() << " from mid to left;" << endl;
                    break;
                case 2:
                    cout << "Move " << dst.top() << " from right to mid;" << endl;
                    break;
                case -2:         
                    cout << "Move " << dst.top() << " from mid to right;" << endl;
                    break;
                default:
                    break;
            }
            record = now;
            return 1;
        }
        return 0;
    
    } 
    
    /*
     *函数介绍:解决限制移动方式的汉诺塔问题的C++实现
     *输入参数:layer为汉诺塔的层数
     *输出参数:无
     *返回值:为移动的歩数
     */
    
    int hanoiStack(int layer)
    {
        stack<int> lS,mS,rS;
        for(int i = layer; i > 0; i--)
        {
            lS.push(i);
        }
        Action record = No;
        int step = 0;
        while(rS.size() != layer)
        {
            step += moveDisc(record,LtoM,lS,mS);
            step += moveDisc(record,MtoL,mS,lS);
            step += moveDisc(record,RtoM,rS,mS);
            step += moveDisc(record,MtoR,mS,rS);
        }
        return step;
    }
    
    /*
     *函数介绍:测试代码
     */
    
    int main ()
    {
        cout << "For 3 storey of Hanoi:" << endl;    
        cout << "It will move " <<hanoiStack(3) <<" steps." << endl;
        return 0;
    }
    View Code

    【一点说明】:

      这次题目的C++复现和左老师所写的略有差别,但是解题思路还是遵循这左老师所提出来的。

      左程云老师还提出了使用递归方式的解法,有兴趣的同学可以去参考原书,下一篇我会将其使用C++的方式实现。

      

    注:

      转载请注明出处;

      转载请注明源思路来自于左程云老师的《程序员代码面试指南》。

  • 相关阅读:
    承载进程 (vshost.exe)
    命令行生成解决方案
    【SQL Server】存储过程的设计概念(3)TSQL的编译和执行过程
    .NET Framework 4
    reflector最新说明
    应用程序域
    vi 编辑器的用法(2013最新整理)
    linux中查看日志的方法
    修改linux主机名的方法介绍
    如何获得桌面上任意一个位置的颜色的 rgb 或者16进制值了
  • 原文地址:https://www.cnblogs.com/PrimeLife/p/5325673.html
Copyright © 2020-2023  润新知