7-5 汉诺塔的非递归实现

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
汉诺塔问题的四种解法
这位博主非常强,给出四种方法,先码住,以后再验证…
此博主解法目录👇
博主的目录

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值