汉诺塔递归实现:
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; void dfs(int n,int now,int to,int user) { if (n==1) { cout<<n<<" from "<<now<<" to "<<to<<endl;; return ; } dfs(n-1,now,user,to); cout<<n<<" from "<<now<<" to "<<to<<endl; dfs(n-1,user,to,now); return ; } int main() { int n; freopen("guiout.txt","w",stdout); //cout<<"请输入汉诺塔的高度n:"; cin>>n; while (n<=0) { // cout<<"汉诺塔的高度为正数"<<endl; // cout<<"请输入汉诺塔的高度n:"; cin>>n; } dfs(n,1,3,2); // system("pause"); return 0; }
汉诺塔的递归实现相信大家都不陌生了,-.-今天通过看了一些博客 汉诺塔非递归算法分析与实现 结合自己发现的一些性质也来写了一个非递归的实现-.-
加入汉诺塔上的盘子从小到大依次为1,2,3------n
发现汉诺塔有一个性质1---- 它所移动第i次时, 所移动的盘子的编号为 i 的二进制从小到大的第一个非0位。
然后利用这个性质---我们就可以知道 每一步所需要移动的盘子是那个了------
然后我就想根据这次移动的盘子和下次移动的盘子能不能确定这次盘子应该移动到哪里呢?? =========== 发现仅仅这两次是不够的---当他们两个在一个塔上我的代码就出错了----------
附错误代码------
#include<cstdio> #include<stack> #include<iostream> #include<algorithm> using namespace std; #define ULL unsigned long long stack<int> stack_shu[4]; ULL pp,ik,e,hh; void gostack(int x,int y) { printf("%d from %d to %d\n",stack_shu[x].top(),x,y); stack_shu[y].push(stack_shu[x].top()); stack_shu[x].pop(); } int wei(ULL x) { int ans=1; while (x%2==0) { ans++; x/=2; } return ans; } int main() { int n,x,y,ci,wx,wy,A,B,ll; while (~scanf("%d",&n)) { for (int i=1;i<4;i++) { while (!stack_shu[i].empty()) stack_shu[i].pop(); } for (int i=n;i>0;i--) stack_shu[1].push(i); e=1ull; for (int i=n;i>0;i--) { ik=1ull; pp=(ik<<(i-1)); cout<<pp<<" "<<ik<<' '<<i<<endl; for (ik;ik<=pp;ik++) { if (ik==1) { if (!stack_shu[1].empty()) { if (i%2==1) { gostack(1,3); } else gostack(1,2); } else { if (i%2==1) { gostack(2,3); } else gostack(2,1); } hh=ik+e; y=wei(hh); x=y; } else if (ik==pp) { if (!stack_shu[1].empty()&&stack_shu[1].top()==i) { gostack(1,3); } else { gostack(2,3); } } else { hh=ik+e; y=wei(hh); wx=0;wy=0; for (int ii=1;ii<=3;ii++) { if (!stack_shu[ii].empty()&&stack_shu[ii].top()==x) wx=ii; if (!stack_shu[ii].empty()&&stack_shu[ii].top()==y) wy=ii; } if (wy==0) { ll=stack_shu[wx].size(); for (int jj=1;jj<=3;jj++) { if (!stack_shu[jj].empty()&&stack_shu[jj].top()==ll+1) { A=jj;break; } } B=6-wx-A; if (ll%2==1) { gostack(wx,A); } else gostack(wx,B); } else gostack(wx,6-wx-wy); x=y; } } } } return 0; }
然后通过看了上面的博客 -.-
性质2 : 发现1号盘子的移动关于3是周期的-.- 所以就可以顺利解决了 -.-
当每次1号盘子移动后--- 加入是A - B ------ 下次会有 B ---- D-------D = A ?C ?
然后移动下一个盘子时,
我们根据性质1 先找到 这个盘子所在的汉诺塔----然后将它移动到没有1 号盘子的那个汉诺塔上-------
然后通过递归与非递归当N=20,N=21时数据的对拍---这个算法应该是正确的=/=
-.- //自己在电脑上打下吧----文件不会上传000000
汉诺塔的非递归实现:
#include<cstdio> #include<cstring> #include<stack> #include<iostream> #include<algorithm> using namespace std; stack<int> stack_shu[4]; #define ULL unsigned long long int dp[3][4]={{0,0,0,0},{1,3,2,0},{1,2,3,0}},ans; void gostack(int x,int y) { cout<<stack_shu[x].top()<<" from "<<x<<" to "<<y<<endl; stack_shu[y].push(stack_shu[x].top()); stack_shu[x].pop(); } int search_wx(ULL x) { int ans=2; while (x%2==0) { ans++; x/=2; } return ans; } int main() { // freopen("out.txt","w",stdout); int n,x,y; ULL ll,wx=1; cin>>n; for (int i=1;i<n;i++) wx*=2; ll=wx-1; ll+=wx; if (n%2==1) { for (int i=0;i<4;i++) dp[0][i]=dp[1][i]; } else { for (int i=0;i<4;i++) dp[0][i]=dp[2][i]; } for (int i=n;i>0;i--) stack_shu[1].push(i); ll/=2;ans=0; x=-1;y=0; for (ULL i=1;i<=ll;i++) { x=(x+1)%3; y=(y+1)%3; gostack(dp[0][x],dp[0][y]); wx=search_wx(i); for (int j=1;j<=3;j++) { if (!stack_shu[j].empty()&&stack_shu[j].top()==wx) { wx=j;break; } } gostack(wx,6-wx-dp[0][y]); } wx=1; for (int j=1;j<=3;j++) { if (!stack_shu[j].empty()&&stack_shu[j].top()==wx) { wx=j;break; } } gostack(wx,3); return 0; }