【PTA】 c语言汉诺塔非递归实现

7-1 汉诺塔的非递归实现 (25 分)

借助堆栈以非递归(循环)方式求解汉诺塔的问题(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

代码

//单左双右,从小到大 
#include"stdio.h"
#include"stdlib.h"
int main()
{
	int N;
	scanf("%d",&N);
	int zhu[4][N+1];
	//第零行中,第一个元素无用,其他元素代表每个盘子所在的行(即柱子)
	//其他行每行代表一个柱子,每个一维数组的首个元素为last
	zhu[3][0]=0;
	zhu[1][0]=0;
	zhu[2][0]=0;
	char biaohao[5]=" abc";
	//puts(biaohao); 
	//空格吃一个空间,使第一个柱子对应a,以此类推 
	for(int aa=N;aa>0;aa--)//给源柱子加上盘子 
	{
		zhu[1][0]+=1;
		zhu[0][zhu[1][0]]=1;//记录所有盘子都在第一行 
		zhu[1][zhu[1][0]]=aa;
		//printf("%d",zhu[1][zhu[1][0]]);
	}
	int sum=0;//左移还是右移
	if(N%2==0)
	sum=1;
	else
	sum=-1;
	int start=1;//准备从哪个柱子开始移动,值为柱子号  
	int next=start+sum;//将移动到的柱子号
	int dang=1;//当前所移动的盘子号 
	int flag=-1;//当前盘子是否移动成功,0为否,1为真 
	int Z=0;//需要的总步数 
	while(zhu[3][0]!=N)
	{
		flag=-1;
		if(next>3)
		next=1;
		if(next<1)
		next=3;
		if(zhu[next][0]==0||zhu[start][zhu[start][0]]<zhu[next][zhu[next][0]])
		{
			zhu[next][0]+=1;
			zhu[next][zhu[next][0]]=zhu[start][zhu[start][0]];
			//盘子向右移动 
			zhu[0][zhu[next][zhu[next][0]]]=next;
			//更新刚刚所移动的盘子所在的柱子号 
			zhu[start][0]-=1;
			//Z+=1;
			//printf("第%d步:%c->%c\n",Z,biaohao[start],biaohao[next]);
			printf("%c -> %c\n",biaohao[start],biaohao[next]);
			flag=1; 
		}
		if(flag==1||next==start)
		//前者为移动成功,后者为移动失败(移动失败时,next必转到start,此时也刚好是一圈) 
		{
			dang+=1;
			if(dang==N+1)
			dang=1;
			while(dang!=zhu[zhu[0][dang]][zhu[zhu[0][dang]][0]])
			//当当前所要移动的盘子不在其柱子的顶层时进入循环 
			{
				dang+=1;
				if(dang==N+1)
			    dang=1;
			}
			start=zhu[0][dang];//更新将移动的盘子所在的柱子号
			//	printf("start为%d\n",start);
			next=start+sum; 
			}
		else
		next+=sum;
			//printf("现在dang是%d ,start是%d,next是%d\n",dang,start,next);			        
		}
	//printf("共需要%d步",Z); //耗时1天。。 
	
}
  • 3
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值