汉诺塔问题(未完)

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

1.递归调用思想
递归问题要注意的不是整个计算过程的实现而是关注完成最后一步所需要的条件再依次向上递归

代码如下:
#include<iostream>
using namespace std;
void move(int n, char A, char C, char B);
int main()
{
	int N;
	char A = 'a', B = 'b', C ='c';
	cin >> N;
	move(N,A,C,B);
	system("pause");
	return 0;
}
void move(int n, char A, char C, char B)
{
	if (n == 0)return;
	move(n - 1, A, B, C);//将n层从a移动到c需要将n-1层从a移动到b
	cout << A << "->" << C << endl;
	move(n - 1, B, C, A);//然后再将n-1层从b移动到c
}

2.非递归实现
主要依据是:所有的汉诺塔移动可以总结为重复的两步,我们假设现在最小的圆盘在a柱子上,柱子a,b,c顺时针放置

第一步:将最小圆盘移动到下一个柱子上,也就是b第二步:对a柱子和c柱子进行顶上最小的元素进行判断,把小一点的那个圆盘移动到大一点的那个圆盘(有空则摞在空柱子上)。重复上述两步就可以得到答案。
注意:如果N是偶数将b柱放在a后,所以如果N是奇数则将c柱放在a后面。
代码如下(N最大超时,等待修改):
#include<iostream>
using namespace std;
const int MAX = 64;
struct st
{
	int s[MAX];//柱子上的圆盘数量
	int top;//最上面的的圆盘
	char name;//柱子的名字(a b c)
	int Top()//取栈顶
	{
		return s[top];
	}
	int pop()//出栈
	{
		return s[top--];
	}
	int push(int x)//入栈
	{
		return s[++top] = x;
	}
};
void creat(st ta[], int n);
long pow(int x, int y);
void hanoi(st ta[], long max);
int main()
{
	int n;
	cin >> n;
	st ta[3];
	creat(ta, n);
	long max = pow(2, n) - 1;
	hanoi(ta, max);
	system("pause");
	return 0;
}
void creat(st ta[], int n)
{
	ta[0].name = 'a';
	ta[0].top = n - 1;
	for (int i = 0; i < n; i++)
		ta[0].s[i] = n - i;
	ta[1].top = ta[2].top = 0;
	for (int i = 0; i < n; i++)
		ta[1].s[i] = ta[2].s[i] = 0;
	if (n % 2 == 0)
	{
		ta[1].name = 'b';
		ta[2].name = 'c';
	}
	else
	{
		ta[1].name = 'c';
		ta[2].name = 'b';
	}
}
long pow(int x, int y)
{
	long sum = 1;
	for (int i = 0; i < y; i++)
		sum *= 2;
	return sum;
}
void hanoi(st ta[], long max)
{
	int k = 0, i = 0;
	int ch;
	while (k < max)
	{
		ch = ta[i % 3].pop();
		ta[(i + 1) % 3].push(ch);
		cout << ta[i % 3].name << " -> " << ta[(i + 1) % 3].name << endl;
		i++;
		k++;//按顺时针方向把圆盘1从现在的柱子移动到下一根柱子
		if (k < max)
		{
			if (ta[(i + 1) % 3].Top() == 0 || ta[(i - 1) % 3].Top() > 0 && ta[(i + 1) % 3].Top() > ta[(i - 1) % 3].Top())
			{
				ch = ta[(i - 1) % 3].pop();
				ta[(i + 1) % 3].push(ch);
				k++;
				cout << ta[(i - 1) % 3].name << " -> " << ta[(i + 1) % 3].name << endl;
			}
			else
			{
				ch = ta[(i + 1) % 3].pop();
				ta[(i - 1) % 3].push(ch);
				k++;
				cout << ta[(i + 1) % 3].name << " -> " << ta[(i - 1) % 3].name << endl;
			}//把非空柱子上的圆盘移动到空柱子上,当两根柱子都为空时,移动较小的圆盘
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值