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