递归算法:汉诺塔问题

问题描述:

古代有一个梵塔,塔内有三个座A、B、C,A座上有64个盘子,盘子大小不等,大的在下,小的在上。有一个和尚想把这64个盘子从A座移动到C座,但每次只能允许移动一个盘子,并且在移动的过程中,3个座上的盘子始终保持大盘在下小盘在上。在移动过程中可以利用B座,要求移动的步骤。输入为A座盘子的数量,输出为盘子的移动方式。

样例输入:

4

样例输出:

1:A->B
2:A->C
1:B->C
3:A->B
1:C->A
2:C->B
1:A->B
4:A->C
1:B->C
2:B->A
1:C->A
3:B->C
1:A->B
2:A->C
1:B->C

问题分析及解决:

这是一道经典的递归算法题。我们假设当前A座有n个盘子(n>=1),如何进行移动盘子。

首先分别讨论盘子数比较少的情形:

1)当n=1时,

直接将A座唯一的盘子移动到C座即可。

2)当n=2时,

先将A座的小盘子移动到B,再将A座稍微大一点的盘子移动到C,最后将小盘子移动到C上。

此时,我们发现语言描述移动盘子已经显得有点费力了,不妨将初始时,盘子的序号从上向下以此排序为1,2,3...n

移动盘子可以写为:

1:A->B,意思为,将序号为1的盘子从A移动到B,这样的描述方式更为清晰明了

3)当n=3时,

1:A->C
2:A->B
1:C->B
3:A->C
1:B->A
2:B->C
1:A->C

当n>3时,盘子的移动变得越来越复杂了,我们需要从复杂的过程中找到规律。

不难发现,如果我们想把所有的盘子从A移动到C,那么,我们肯定是要先把n-1个盘子以C为过度从A移动到B,然后将最后一个盘子移动到C,最后再将B座上的n-1个盘子以A为过度从B移动到C,便可以完成整个的操作过程。那么,n-1个盘子的移动过程也是同样的套路,从n-2个盘子的移动开始,依次类推。从而可以写出相关的递归算法代码。

代码

#include <iostream>
using namespace std;

//n为A座初始的个数,Order_n为自上而下的序号,Hanoi的功能是将A上n个盘子移动到C上,B作为中间的辅助
void Hanoi(int n, char A, char B, char C,int Order_n)
{
	if (n == 1)
	{
		cout << Order_n << ":" << A << "->" << C << endl;//若A座只有一个,则直接将该盘子移动到C座上
		return;
	}
	//当n不为0时,主要有3个操作
	Hanoi(n - 1, A, C, B, Order_n);//先将n-1个盘子从A移动到B
	cout << Order_n + n - 1 << ":" << A << "->" << C << endl;//将最后一个标号的盘子从A移动到C
	Hanoi(n - 1, B, A, C, Order_n);//最后再将B上n-1个盘子从B移动到C
}

void main()
{
	char A, B, C;
	int n;
	A = 'A';
	B = 'B';
	C = 'C';
	cin >> n ;
	Hanoi(n, A, B, C, 1);//这里入参多了A,B,C,可以自行定义座子的名称
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值