Hanoi迭代解决方案

Hanoi Iterative solution

本文关键字:解决方案 迭代 Hanoi      更新时间:2023-10-16

如Wikepedia 中所述,我正试图在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 
==============

我在俯瞰什么?任何建议都是有用的。

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

我有一半的时间交替使用源和目的地,正如你提到的维基文章中所说的那样。在最小磁盘和次最小磁盘之间交替

我还将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;
}