非递归算法:
根据圆盘的数量确定柱子的排放顺序:
若n为偶数,按顺时针方向依次摆放 A B C;
若n为奇数,按顺时针方向依次摆放 A C B。
然后进行如下操作:
(1)按顺时针方向把圆盘1从现在的柱子移动到下一根柱子,即当n为偶数时,若圆盘1在柱子A,则把它移动到B;若圆盘1在柱子B,则把它移动到C;若圆盘1在柱子C,则把它移动到A。
(2)接着,把另外两根柱子上可以移动的圆盘移动到新的柱子上。即把非空柱子上的圆盘移动到空柱子上,当两根柱子都非空时,移动较小的圆盘。
(3)反复进行(1)(2)操作,最后就能按规定完成汉诺塔的移动。
C++实现:
#include<bits/stdc++.h> using namespace std; typedef unsigned long long LL; struct Hanoi { int n; struct Tower { char Name; stack<int> Disks; }Tow[3]; void init(int num) { n=num; for(int i=0;i<3;i++) { Tow[i].Name='A'+i; while(!Tow[i].Disks.empty()) Tow[i].Disks.pop(); } for(int i=n;i>=1;i--) Tow[0].Disks.push(i); } void solve() { LL cnt=0,cnt_max=(1<<n)-1; while(cnt<cnt_max) { cnt++; int flag1,flag2; if(cnt%2)//第奇数次的移动 { for(int i=0;i<3;i++) if(!Tow[i].Disks.empty() && Tow[i].Disks.top()==1) flag1=i; if(n%2)//n为奇数 flag2=((flag1-1)+3)%3; else flag2=(flag1+1)%3; } else//第偶数次的移动 { flag1=flag2=-1; for(int i=0;i<3;i++) { if(!Tow[i].Disks.empty() && Tow[i].Disks.top()==1) continue; if(flag1==-1) flag1=i; else if(flag2==-1) flag2=i; } if(!Tow[flag1].Disks.empty() && !Tow[flag2].Disks.empty()) { if(Tow[flag1].Disks.top()>Tow[flag2].Disks.top()) swap(flag1,flag2); } else { if(Tow[flag1].Disks.empty()) swap(flag1,flag2); } } cout<<cnt<<": "<<"Move disk "<<Tow[flag1].Disks.top()<<" from "<<Tow[flag1].Name<<" to "<<Tow[flag2].Name<<endl; Tow[flag2].Disks.push(Tow[flag1].Disks.top()); Tow[flag1].Disks.pop(); } } }hanoi; int main() { int n; cout<<"输入圆盘个数:"; cin>>n; hanoi.init(n); hanoi.solve(); }
递归算法:
设Hanoi(n,a,c,b)表示n个圆盘在a柱上,通过服从汉诺塔规则的若干步骤移动,在b柱的辅助下,全部按原顺序移动到了c柱上;
#include<bits/stdc++.h> using namespace std; typedef unsigned long long LL; LL cnt; void Hanoi(int n,char a,char c,char b) { if(n==1) { cout<<++cnt<<": "<<"Move disk "<<n<<" from "<<a<<" to "<<c<<endl; return; } Hanoi(n-1,a,b,c); cout<<++cnt<<": "<<"Move disk "<<n<<" from "<<a<<" to "<<c<<endl; Hanoi(n-1,b,c,a); return; } int main() { int n; cout<<"输入圆盘个数:"; cin>>n; cnt=0; Hanoi(n,'A','C','B'); }