栈解决汉诺塔问题

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

  • 现在限制不能从最左侧的塔直接移动到最右侧,也不能从最右侧直接移动到最左侧,而是必须经过中间。
  • 求当塔有N层的时候,打印最优移动过程和最优移动总步数。
  • 在走出最少步数过程中的任何时刻,四个动作中只有一个动作不违反小压大和相邻不可逆原则(相邻的两次操作不互为逆操作如:MtoR和RtoM),另外三个动作一定都会违反。
#include <iostream>
#include <stack>
using namespace std;

enum Act {                //    利用绝对值解决逆操作问题 感谢Stan提供的思路
    No = 0,
    LtoM = 1,
    MtoL = -1,
    RtoM = 2,
    MtoR = -2
};

int move(Act& reAct, Act nowAct, stack<int>& src, stack<int>& dst) {
    if (!src.empty() && (abs(reAct) != abs(nowAct)) && (dst.empty() || src.top() < dst.top())) {
        dst.push(src.top());
        src.pop();
        switch (nowAct){
        case 1:
            cout << "Move " << dst.top() << " from L to M" << endl;
            break;
        case -1:
            cout << "Move " << dst.top() << " from M to L" << endl;
            break;
        case 2:
            cout << "Move " << dst.top() << " from R to M" << endl;
            break;
        case -2:
            cout << "Move " << dst.top() << " from M to R" << endl;
            break;
        }
        reAct = nowAct;
        return 1;
    }
    return 0;
}

int solveHanoi(int l) {                        //    解决从左往右移动的问题
    stack<int> lS, mS, rS;
    for (int i = l; i > 0; i--)                //    修改此处可决定源栈
    {
        lS.push(i);
    }
    Act record = No;
    int step = 0;
    while (rS.size() != l)                    //    修改此处可决定目的栈
    {
        step += move(record, LtoM, lS, mS);
        step += move(record, MtoL, mS, lS);
        step += move(record, RtoM, rS, mS);
        step += move(record, MtoR, mS, rS);
    }
    return step;
}

int main()
{
    cout << "Solve 3 Hanoi LtoR:" << endl;
    cout << "I will move " << solveHanoi(3) << " steps" << endl;
    return 0;
}

 

posted @ 2019-07-30 15:01  木子石页  阅读(275)  评论(0编辑  收藏  举报