河内塔量组合?

时间:2013-04-13 08:38:24

标签: c++ algorithm towers-of-hanoi

最近我正在接受C ++ Develpoer职位的采访,我被要求编写一个解决3列和1000000光盘的河内塔拼图的程序,程序必须写入移动到磁盘的输出(“1-> ; 3“,”1> 2“,......等等),我告诉他们这将是一个非常大的解决方案,因为河内塔的最小移动量是2次幂n - 1和1000000这将是一个非常大的数字,不适合任何硬盘驱动器,他们说经典算法是错误的,有一个算法解决这个难题,即使对于发烧移动的1000000光盘。我想知道是否存在这样的算法或他们只是骗我?

谢谢Timur。

2 个答案:

答案 0 :(得分:0)

输出确实太大(如你所说,输入大小呈指数),但算法以递归方式编写相当简单。也许这就是他们的意思。

如果你愿意,我可以提供算法。

编辑:只是为了完整性,我提供了算法(在Python中,但在C ++中的实现将基本相同):

n = 3
# using 4 elements just so we're 1-based with three towers
towers = [ [], range(n, 0, -1), [], [] ]

def move (orig, dest, n):
    if n == 1:
        elem = towers[orig].pop()
        print 'moving %d from %d to %d' % (elem, orig, dest)
        towers[dest].append(elem)
    else: 
        through = dest ^ orig
        move(orig, through, n-1)
        move(orig, dest, 1)
        move(through, dest, n-1)

move(1, 3, n)

答案 1 :(得分:0)

这是我为nhahtdh承诺的代码。

#include <iostream>
#include <conio.h>
#include <math.h>
#include <iomanip>

using namespace std;
char disc[2000000]={0};
int n;
bool validate(int num,int target){
    int t=num+1;
    while(t<n){
        if ((disc[num]==disc[t])||(disc[t]==target))return false;
        t++;
    };
    return true;
};  
int main()
{
    __int64 k=0;
    cout<<"Enter number of discs:";cin>>n;
    cout<<"This would be a "<<setprecision(1000)<<pow(2,n)-1<<" combinations !"<<endl;
    cout<<"To START press a key!"<<endl;
    _getch();
    int num=0,cur=0,t=0,nn=0;
    while(num<n){
        t=2;nn=num;
        while(nn<n){
            if(disc[nn]==t){nn++;continue;}
            if(validate(nn,t)){
                if(nn==num)num++;
                k++;cout<<disc[nn]+1<<"->"<<t+1<<":"<<k<<" move"<<endl;
                disc[nn]=t;
                nn++;
                continue;
            }
            if((disc[nn]==0)&&(t==2)){nn++;t=1;continue;}
            if((disc[nn]==0)&&(t==1)){nn++;t=2;continue;}
            if((disc[nn]==1)&&(t==2)){nn++;t=0;continue;}
            if((disc[nn]==1)&&(t==0)){nn++;t=2;continue;}
            if((disc[nn]==2)&&(t==1)){nn++;t=0;continue;}
            if((disc[nn]==2)&&(t==0)){nn++;t=1;continue;}
        };
    };
    return 0;
}

我希望你能理解,但如果没有给我发电子邮件给atlantic-sys@mail.ru我可以详细解释。