【问题标题】:Hanoi Iterative solution河内迭代解决方案
【发布时间】:2016-03-19 05:55:02
【问题描述】:

我正在尝试在 C++ 中实现汉诺塔迭代解决方案,如维基百科中所述

更简单的迭代解决方案

在最小和次小的磁盘之间交替,按照适当情况的步骤操作:

对于偶数个磁盘:

*make the legal move between pegs A and B*
*make the legal move between pegs A and C*
*make the legal move between pegs B and C*
*repeat until complete*

对于奇数个磁盘:

*make the legal move between pegs A and C*
*make the legal move between pegs A and B*
*make the legal move between pegs C and B*
*repeat until complete*

在每种情况下,总共进行了 2n-1 步。

到目前为止我写的代码是

#include <iostream>
#include <list>    

const int SIZE = 5;
int pCount = 1;
using namespace std;    

list<int> *lhs;
list<int> *mid;
list<int> *rhs;    


void initTower(int size);    

void printPeg(list<int> p);    

bool printTower();    

bool isEven(list<int> l);    

bool move(list<int> *from, list<int> *to);    

int main() {    

    lhs = new list<int>;
    mid = new list<int>;
    rhs = new list<int>;    


    initTower(SIZE);
    printTower();
    bool run = true;
    while (run) {
        int n = SIZE;    

        if (n % 2 == 0) // even
        {
            move(lhs,mid);
            move(lhs,rhs);
            move(mid,rhs);    

        }else{    

            move(lhs,rhs);
            move(lhs,mid);
            move(rhs,mid);    

        }    


        if (rhs->size() == SIZE) {
            run = false;    

        }
    }    


    return 0;
}    


bool isEven(list<int> l) {    

    return l.size() % 2 == 0;    

}    

void initTower(int size) {    

    while (size--)
        lhs->push_back(size + 1);
}    

void printPeg(list<int> p) {    

    if (p.empty()) {
        cout << "empty" << endl;
    } else {
        for (int i: p)
            cout << i << " ";
        cout << endl;
    }    

}    

bool printTower() {    

    cout << "==============" << endl;
    cout << "=====top=======" << pCount++ << endl;
    printPeg(*lhs);
    printPeg(*mid);
    printPeg(*rhs);
    cout << "==============" << endl << endl;    

    return true;    

}    

bool move(list<int> *from, list<int> *to) {
    bool vailidMove = false;
    int fVal = 0;
    int toVal = 0;    

    if (!from->empty())
        fVal = from->back();    

    if (!to->empty())
        toVal = to->back();    


    if ((fVal < toVal || toVal == 0) && (fVal > 0 && fVal != 0)) {
        from->pop_back();
        to->push_back(fVal);
        vailidMove = true;
        printTower();
    }
    return vailidMove;
}    

我对上述程序的输出是。

==============
=====top=======1
5 4 3 2 1 
empty
empty
==============    

==============
=====top=======2
5 4 3 2 
empty
1 
==============    

==============
=====top=======3
5 4 3 
2 
1 
==============    

==============
=====top=======4
5 4 3 
2 1 
empty
==============    

==============
=====top=======5
5 4 
2 1 
3 
==============

我忽略了什么?任何建议都是有帮助的。

【问题讨论】:

  • 到底是什么问题?
  • 哦对不起..让我添加我的输出。这可能会有所帮助
  • 总共移动次数是多少?能被3整除吗;)

标签: c++ algorithm iteration


【解决方案1】:

如果fVal &gt; toVal(或者你会停止而不是完成算法),我在你的移动函数中添加了一个条件来移动极点。

正如您所指的 wiki 文章中所说,我有一半时间交替了源和目标。 在最小和次小的磁盘之间交替

我还将 pCount 初始化更改为 0 而不是 1,因为第一次打印仅列出起始塔,而不是操作。但是如果你想要的话,你可以再放 1。

PS:我测试了这段代码,它工作得非常好,给2^n-1 操作就像它应该做的那样。

#include <iostream>
#include <list>

const int SIZE = 12;
int pCount = 0;
using namespace std;

list<int> *lhs;
list<int> *mid;
list<int> *rhs;


void initTower(int size);

void printPeg(list<int> p);

bool printTower();

bool isEven(list<int> l);

bool move(list<int> *from, list<int> *to);

int main() {

    lhs = new list<int>;
    mid = new list<int>;
    rhs = new list<int>;

    initTower(SIZE);
    printTower();
    bool run = true;
    bool lowest = false;
    while (run) {
        lowest = !lowest;
        int n = SIZE;

        if (n % 2 == 0) // even
        {
            if (lowest){
                move(lhs,mid);
                if (rhs->size() == SIZE) {
                    break;
                }
                move(lhs,rhs);
                move(mid,rhs);
            }else{
                move(mid,lhs);
                if (rhs->size() == SIZE) {
                    break;
                }
                move(rhs,lhs);
                move(rhs,mid);
            }
        }else{
            if (lowest){
                move(lhs,rhs);
                move(lhs,mid);
                if (rhs->size() == SIZE) {
                    break;
                }
                move(mid,rhs);
            }else{
                move(rhs,lhs);
                move(mid,lhs);
                if (rhs->size() == SIZE) {
                    break;
                }
                move(rhs,mid);
            }
        }

        lowest = !lowest;
    }


    return 0;
}


bool isEven(list<int> l) {

    return l.size() % 2 == 0;

}

void initTower(int size) {

    while (size--)
        lhs->push_back(size + 1);
}

void printPeg(list<int> p) {

    if (p.empty()) {
        cout << "empty" << endl;
    } else {
        for (int i: p)
            cout << i << " ";
        cout << endl;
    }

}

bool printTower() {

    cout << "==============" << endl;
    cout << "=====top=======" << pCount++ << endl;
    printPeg(*lhs);
    printPeg(*mid);
    printPeg(*rhs);
    cout << "==============" << endl << endl;

    return true;

}

bool move(list<int> *from, list<int> *to) {
    bool vailidMove = false;
    int fVal = 0;
    int toVal = 0;

    if (!from->empty())
        fVal = from->back();

    if (!to->empty())
        toVal = to->back();

    if ((fVal < toVal || toVal == 0) && fVal > 0) {
        from->pop_back();
        to->push_back(fVal);
        vailidMove = true;
        printTower();
    }else if ((fVal > toVal || fVal == 0) && (toVal > 0 && toVal != 0)) {
        from->push_back(toVal);
        to->pop_back();
        vailidMove = true;
        printTower();
    }
    return vailidMove;
}

【讨论】:

  • 感谢您的意见。我的代码是 (2^n -1) *2 而不是 (2^n-1) 有什么原因吗?
  • 我更新了我的答案。对不起我的代码质量,我没有太多时间做这个,但现在它可以在 2^n-1 上正常工作。您需要在循环之间交替源和目标。我在河内的 wiki 文章中找到了这个。抱歉耽搁了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-22
  • 2013-08-31
  • 2020-06-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多