汉诺塔的变形题目:

现在有多个柱子,柱子上有若干盘子,盘子的摆放要求编号小的盘子一定在编号大的盘子的上面。初始时,若干个盘子分散在这些柱子上,要求实现一个算法,将盘子移动到其他柱子上。

这个题目其实并不是很难,但是一定要分析清楚和能够熟练使用递归算法。

 

#include <iostream>
#include <list>
#include <stack>
#include <algorithm>

using namespace std;

class HanoiWithStatus
{
public:
        HanoiWithStatus(int n)
        {
                m_pegs = n;
                InitialPegStatus = new list<int>[n];
                FinalPegStatus = new list<int>[n];
        }
        void Rearrange();
        void MoveToFinal();
        void MoveToContainer(int i);
        void Move();
        list<int>* InitialPegStatus;
        list<int>* FinalPegStatus;
        void move(int i, int src, int dest, int buffer);
        void MoveOnePlateToTarget(int  plate);
private:
        int m_pegs;
        int m_plates;
};

void HanoiWithStatus::Rearrange()
{
        m_plates = 0;
        for(int i=0;i<m_pegs;i++)
                m_plates +=InitialPegStatus[i].size();
        for (int i= 0 ;i<m_plates;i++)
        {
                cout<<"Arranging "<<i<<endl;
                MoveToContainer(i);
        }

        for (int i= 0 ;i<m_pegs;i++)
                cout<<InitialPegStatus[i].size()<<endl;
}
void HanoiWithStatus::move(int i, int src, int dest, int buffer)
{
        if(i>=0)
        {
                move(i-1, src, buffer, dest);
                InitialPegStatus[src].remove(i);
                InitialPegStatus[dest].push_front(i);
                cout<<"Move "<<i<<" from "<<src<<" to "<<dest<<endl;
                move(i-1, buffer, dest, src);
        }
}
void HanoiWithStatus::MoveToContainer(int plate)
{
        int owningIndex = -1, containingIndex = -1;
        int bufferIndex = -1;
        for(int i= 0;i<m_pegs;i++)
        {
                list<int>::iterator itr = find(InitialPegStatus[i].begin(), InitialPegStatus[i].end(), plate);
                if(itr == InitialPegStatus[i].end())
                        continue;
                else{
                        owningIndex = i;
                        break;
                }
        }
        if(owningIndex >= 0)
        {
                for(int i= 0;i<m_pegs;i++)
                {
                        list<int>::iterator itr = find(InitialPegStatus[i].begin(), InitialPegStatus[i].end(), plate+1);
                        if(itr == InitialPegStatus[i].end())
                                continue;
                        else{
                                containingIndex = i;
                                break;
                        }
                }
                for(int i = 0;i<m_pegs;i++)
                        if(i != owningIndex && i != containingIndex)
                        {
                                bufferIndex = i;
                                break;
                        }
                if(containingIndex>=0 && owningIndex != containingIndex)
                        move(plate, owningIndex, containingIndex, bufferIndex);
        }
}
void HanoiWithStatus::MoveToFinal()
{
        int maxPlate = -1;
        for(int i= 0 ;i<m_pegs;i++)
        {
                if(InitialPegStatus[i].size()>0)
                {
                        maxPlate = InitialPegStatus[i].back();
                        break;
                }
        }
        for(int i = maxPlate;i>=0;i--)
        {
                cout<<"Moving "<<i<<endl;
                MoveOnePlateToTarget(i);
        }
}
void HanoiWithStatus::MoveOnePlateToTarget(int  plate)
{
        int owningIndex = -1, finalIndex = -1;
        int bufferIndex = -1;
        for(int i= 0;i<m_pegs;i++)
        {
                list<int>::iterator itr = find(InitialPegStatus[i].begin(), InitialPegStatus[i].end(), plate);
                if(itr == InitialPegStatus[i].end())
                        continue;
                else
                {
                        owningIndex = i;
                        break;
                }
        }
        if(owningIndex >= 0)
        {
                for(int i= 0;i<m_pegs;i++)
                {
                        list<int>::iterator itr = find(FinalPegStatus[i].begin(), FinalPegStatus[i].end(), plate);
                        if(itr == FinalPegStatus[i].end())
                                continue;
                        else
                        {
                                finalIndex = i;
                                break;
                        }
                }
                for(int i = 0;i<m_pegs;i++)
                {
                        list<int>::iterator itr = InitialPegStatus[i].begin();
                        if(itr == InitialPegStatus[i].end() || *itr >plate)
                        {
                                bufferIndex = i;
                                break;
                        }
                }
                if(finalIndex>=0 && owningIndex != finalIndex)
                        move(plate, owningIndex, finalIndex, bufferIndex);
        }
}

void HanoiWithStatus::Move()
{
        Rearrange();
        MoveToFinal();
}

int main(int argc,char **argv)
{
        HanoiWithStatus* hanoi = new HanoiWithStatus(4);
        hanoi->InitialPegStatus[0].push_front(6);
        hanoi->InitialPegStatus[0].push_front(5);
        hanoi->InitialPegStatus[1].push_front(3);
        hanoi->InitialPegStatus[2].push_front(4);
        hanoi->InitialPegStatus[3].push_front(2);
        hanoi->InitialPegStatus[3].push_front(1);
        hanoi->InitialPegStatus[3].push_front(0);
        hanoi->FinalPegStatus[3].push_front(6);
        hanoi->FinalPegStatus[3].push_front(5);
        hanoi->FinalPegStatus[3].push_front(4);
        hanoi->FinalPegStatus[3].push_front(3);
        hanoi->FinalPegStatus[3].push_front(2);
        hanoi->FinalPegStatus[3].push_front(1);
        hanoi->FinalPegStatus[3].push_front(0);

        hanoi->Move();
}