递归解决汉诺塔问题

汉诺塔问题比较经典,这里修改--下游戏规则:

  • 现在限制不能从最左侧的塔直接移动到最右侧,也不能从最右侧直接移动到最左侧,而是必须经过中间。
  • 求当塔有N层的时候,打印最优移动过程和最优移动总步数。

解题思路:

如果剩下N层塔,从最上到最下依次为1~N,则有如下判断:
1.如果剩下的N层塔都在“左”,希望全部移到“中”,则有三个步骤。
  1)将1~N-1层塔先全部从“左”移到“右",明显交给递归过程。
  2)将第N层塔从“左”移到“中”。
  3)再将1~N-1层塔全部从“右”移到“中”,明显交给递归过程。
2.如果把剩下的N层塔从“中”移到“左”,从“中”移到“右”,从“右”移到“中”,过程与情况1同理,一样是分解为三步,在此不再详述。
3.如果剩下的N层塔都在“左”,希望全部移到“右”,则有五个步骤。
  1)将1~N-1层塔先全部从“左”移到“右”,明显交给递归过程。
  2)将第N层塔从“左”移到“中”。
  3)将1~N-1层塔全部从“右”移到“左”,明显交给递归过程。
  4)将第N层塔从“中”移到“右”。
  5)最后将1~N-1层塔全部从“左”移到“右”,明显交给递归过程。
4.如果剩下的N层塔都在“右",希望全部移到“左”,过程与情况3同理,一样是分解为五步,在此不再详述。

#include <iostream>
#include <string.h>
using namespace std;

int hanoiRec(int layer, string src, string dst)
{
    if (1 > layer)
        return 0;
    if (1 == layer)            //只有一层时(递归的退出检测)
    {
        if ("mid" == src || "mid" == dst) //源端或目的端为中间的情况
        {
            cout << "move 1 form " << src << " to " << dst << endl;
            return 1;
        }
        else         //源端或目的端为非中间的情况(左/右)
        {
            cout << "move 1 form " << src << " to mid" << endl;
            cout << "move 1 form mid to " << dst << endl;
            return 2;
        }
    }

    //有多层的情况
    if ("mid" == src || "mid" == dst) //源端或目的端为mid的情况(普通的汉诺塔问题)
    {
        //获得辅助端(左/右)
        string aux = ("left" == src || "left" == dst) ? "right" : "left";
        //第一步,将1~layer-1层从源端移动到辅助端
        int step1 = hanoiRec(layer - 1, src, aux);
        //第二步,将第layer层移动到目的端
        int step2 = 1;
        cout << "move " << layer << " from " << src << " to " << dst << endl;
        //第三步,将1~layer-1层从辅助端移动到目的端
        int step3 = hanoiRec(layer - 1, aux, dst);
        return step1 + step2 + step3;
    }
    else  //源端和目的端为非mid的情况
    {
        //第一步,将1~layer-1层从源端移动到目的端
        int step1 = hanoiRec(layer - 1, src, dst);
        //第二步,将第layer层从源端移动到mid端(即mid端为辅助端)
        int step2 = 1;
        cout << "move " << layer << " from " << src << " to mid" << endl;
        //第三步,将1~layer-1层从目的端移动到源端
        int step3 = hanoiRec(layer - 1, dst, src);
        //第四步,将第layer层从mid端移动到目的端
        int step4 = 1;
        cout << "move " << layer << " from mid to " << dst << endl;
        //第五步,将1~layer-1层从源端移动到目的端
        int step5 = hanoiRec(layer - 1, src, dst);
        return step1 + step2 + step3 + step4 + step5;
    }
}

int main()
{
    int step = hanoiRec(2, "mid", "right");
    cout << "It will move " << step << " steps." << endl;
    return 0;
}
posted @ 2019-07-29 16:22  木子石页  阅读(454)  评论(0编辑  收藏  举报