非曰能,但好学,欢迎一起交流学习

问题分析

递归是解决汉诺塔问题最常见的做法,大家都不懒得写,我就来写写~

递归步骤分析

汉诺塔问题要求在移动过程中,不出现大的盘子压在小的盘子上。如下图需要讲src柱子上的n个盘子移动到target上柱子上。假设我们已经可以按照规则将上面n-1个柱子移动另外的柱子上。,怎完成n个盘子移动的任务步骤为:

  1. 将src柱子上的上面n-1层盘子移动到mid柱子(非src和target的中间过渡的柱子)上。
  2. 将第n的盘子移动到target上柱子上。
  3. 将mid柱子上的n-1个盘子移动到target柱子上。
    对于n=1的情况,不需要借助mid柱子,直接将一个盘子拎到target上就ok了。

移动次数分析

表示移动n个盘子需要移动的次数,则有移动次数的递推关系式
可以计算得到移动次数,即移动过程中存在的状态数为次.

代码实现

递归中的步骤实现是明显的stack压栈出栈操作,但考虑到可视化的方便,这里采用用三个vector来表示三个塔上串的柱子状态(本人觉得stack的数据结构是C++中最没必要的数据结构)。实现时可以考虑分成两层:一是“逻辑层”,将负责每个移动过程中修改三个vector变量;另一个为“可视化层”,负责根据三个vector的状态,来打印出结果。

最后附上本人拙劣的代码如下。

#include <bits/stdc++.h>

using namespace std;

class Solution
{
    public:
    int n;
    vector<int> A[3];
    void read()
    {
        cin>>n;
        for(int i=0; i<n; i++)
            A[0].push_back(n-i);
    }
    void printDim()
    {
        int cols=3*(2*n+1)+4;
        for(int j=0; j<cols; j++)
            printf("-");
        printf("\n");
    }
    void move(int n, int src, int target)
    {
        if(n==1)
        {
            A[target].push_back(A[src].back());
            A[src].pop_back();
            printDim();
            show();
            return ;
        }
        int mid=0;
        for(; mid<3; mid++)
            if(mid!=src && mid!=target)
                break;
        move(n-1,src,mid);
        A[target].push_back(A[src].back());
        A[src].pop_back();
        printDim();
        show();

        move(n-1,mid,target);
    }
    void show()
    {
        // show the 3 vectors in A
        int cols=3*(2*n+1)+4;
        for(int j=0; j<cols; j++)
            printf(".");
        printf("\n");

        for(int r=0; r<=n; r++)
        {
            printf(".");
            for(int k=0; k<3; k++)
            {
                int tmp = n-r<A[k].size()? A[k][n-r] : 0;
                for(int j=0; j<n-tmp; j++)
                    printf(".");
                if(tmp==0)
                    printf("|");
                else
                {
                    for(int j=0; j<1+2*tmp; j++)
                        printf("*");
                }
                for(int j=0; j<n-tmp; j++)
                    printf(".");
                printf(".");
            }
            printf("\n");
        }   
    }

    void process()
    {
        show();
        if(n%2==0)
            move(n,0,2);
        else
            move(n,0,1);
    }
};

int main()
{
    Solution s;
    s.read();
    s.process();
    return 0;
}