7-5 汉诺塔的非递归实现
借助堆栈以非递归(循环)方式求解汉诺塔的问题(n, a, b,
c),即将N个盘子从起始柱(标记为“a”)通过借助柱(标记为“b”)移动到目标柱(标记为“c”),并保证每个移动符合汉诺塔问题的要求。
输入格式:
输入为一个正整数N,即起始柱上的盘数。
输出格式:
每个操作(移动)占一行,按柱1 -> 柱2的格式输出。
输入样例:
3
输出样例:
a -> c
a -> b
c -> b
a -> c
b -> a
b -> c
a -> c
代码如下:
版本一:递归解法
C语言递归实现汉诺塔问题(这是我大一上从C语言习题书上扫描提取出来的代码…)
递归算法大概是最简洁最容易理解的解法
⚠️注意这道题输出一定要用printf,否则最后一个测试点TLE
#include<bits/stdc++.h>
using namespace std;
void Hanoi(int n,char a,char c,char b){
if(n==1) printf("%c -> %c\n",a,c);
else{
Hanoi(n-1,a,b,c);
printf("%c -> %c\n",a,c);
Hanoi(n-1,b,c,a);
}
}
int main(){
int N;
scanf("%d",&N);
Hanoi(N,'a','c','b');
return 0;
}
版本二:递归解法
参考👇链接照着博主模拟出来,此方法用数学解决不好理解
参考链接
⚠️注意这道题输出一定要用printf,否则最后一个测试点TLE
#include<bits/stdc++.h>
using namespace std;
stack<int> a,b,c; //a:起始柱;b:借助住;c:目标柱
char pin[3] = {'a','b','c'}; //默认n为偶数按顺时针摆放为abc
void Move(char a,char c){
printf("%c -> %c\n",a,c);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int N,i;
cin >> N;
for(i=N;i>0;--i){
a.push(i);
}
if(N%2){ //n为奇数按顺时针摆放为acb
pin[1] = 'c';
pin[2] = 'b';
}
for(int i=1;;i++){ //反复进行⑴⑵操作
if(i%3==1){ //圆盘1在柱子A,则把它移动到B
Move(pin[0],pin[1]);
b.push(a.top());
a.pop();
if(b.size()==N||c.size()==N) break; //如果b/c上的盘子为N个说明移动好了,可以退出
if(c.empty()&&!a.empty()){ //c空 把非空柱子上的圆盘移动到空柱子上
Move(pin[0],pin[2]);
c.push(a.top());
a.pop();
}else if(a.empty()&&!c.empty()){ //a空 把非空柱子上的圆盘移动到空柱子上
Move(pin[2],pin[0]);
a.push(c.top());
c.pop();
}else{ //当两根柱子都非空时,移动较小的圆盘。
if(c.top()>a.top()){
Move(pin[0],pin[2]);
c.push(a.top());
a.pop();
}else{
Move(pin[2],pin[0]);
a.push(c.top());
c.pop();
}
}
}else if(i%3==2){ //圆盘1在柱子B,则把它移动到C
Move(pin[1],pin[2]);
//cout << pin[1] << " -> " << pin[2] << endl;
c.push(b.top());
b.pop();
if(b.size()==N||c.size()==N) break; //如果b/c上的盘子为N个说明移动好了,可以退出
if(b.empty()&&!a.empty()){ //b空 把非空柱子上的圆盘移动到空柱子上
Move(pin[0],pin[1]);
b.push(a.top());
a.pop();
}else if(a.empty()&&!b.empty()){ //a空 把非空柱子上的圆盘移动到空柱子上
Move(pin[1],pin[0]);
a.push(b.top());
b.pop();
}else{ //当两根柱子都非空时,移动较小的圆盘。
if(b.top()>a.top()){
Move(pin[0],pin[1]);
b.push(a.top());
a.pop();
}else{
Move(pin[1],pin[0]);
a.push(b.top());
b.pop();
}
}
}else{ //圆盘1在柱子C,则把它移动到A
Move(pin[2],pin[0]);
a.push(c.top());
c.pop();
if(b.size()==N||c.size()==N) break; //如果b/c上的盘子为N个说明移动好了,可以退出
if(b.empty()&&!c.empty()){ //b空 把非空柱子上的圆盘移动到空柱子上
Move(pin[2],pin[1]);
b.push(c.top());
c.pop();
}else if(c.empty()&&!b.empty()){ //c空 把非空柱子上的圆盘移动到空柱子上
Move(pin[1],pin[2]);
c.push(b.top());
b.pop();
}else{ //当两根柱子都非空时,移动较小的圆盘。
if(c.top()>b.top()){
Move(pin[1],pin[2]);
c.push(b.top());
b.pop();
}else{
Move(pin[2],pin[1]);
b.push(c.top());
c.pop();
}
}
i=0;
}
}
return 0;
}
版本N
汉诺塔问题的四种解法
这位博主非常强,给出四种方法,先码住,以后再验证…
此博主解法目录👇