汉诺塔问题

cxl

问题:设有3根编号分别为A、B、C的柱子,在A柱上有n个盘子,每一个盘子都比它下面的一个盘子小一些,最下面的盘子是最大的,若要把A上的盘子全部按以下要求移到C上,则应该按什么顺序移动?

要求:

1、一次只能移动一个盘子

2、移动过程中大盘子不能放在小盘子上面

3、在移动过程中盘子可以放在A、B、C的任意一个上面。

思路:

我们先考虑最简单的情况,若A上只有一个盘子,则我们只需要将它移动到C上即可。

 A-->C

cxl

若A上有两个盘子,我们就需要借助B的帮助了,将B作为中转站,先将小盘子放在B上,再将大盘子放在C上,最后将B上的小盘子放在C上。

 A-->B
 A-->C
 B-->C

若有3个盘子,还是首先借助B,将前两个小盘子放在B上,再将最大的盘子放在C上,然后再借助A将两个小盘子依次按要求放在C上。

cxl

若有4个盘子,我们也可以按照上面的思路进行

cxl
cxl

五阶汉诺塔问题

cxl

因此我们得到了问题的解法:

当n=1时,只要从A移动到C即可;

当n>1时,此时需要借助另一个柱子的帮助来移动。我们将移动的步骤分解一下:

1、将A上的n-1个盘子借助C移动到B上;
2、将A上第n个盘子(即在移动完后剩下的那一个盘子)移动到C上;
3、最后将B上剩余的n-1个盘子借助A盘移动到C上。

至此,我们解决了汉诺塔问题中该如何摆放的问题。

汉诺塔问题的递归体(程序中自相似的部分):

移动n-1个盘子和移动n个盘子的过程是相似的,但整个过程又不完全一样,因为盘子摆放的柱子变了。

汉诺塔问题的递归出口(递归终止语句):

n=1的状态。

下面我们从递归和栈的角度去理解汉诺塔问题中的递归过程

我们以三阶汉诺塔问题为例

在这里插入图片描述

在栈中即为:

(6行,2,‘B’,‘A’,‘C’)

(4行,2,‘B’,‘A’,‘C’)

(6行,3,‘A’,‘B’,‘C’)

(6行,2,‘A’,‘C’,‘B’)

(4行,2,‘A’,‘C’,‘B’)

(4行,3,‘A’,‘B’,‘C’)

程序:

void move(char a, char b)//移动函数,表示将a上的一个盘子移动到b上
{
	printf("%c-->%c", a, b);
}

void hanoi(int n, char x, char y, char z)//n为盘子的总数,x为需要移动的柱子,y为协助的中转的柱子,z为盘子最后转移到的柱子
{
	if(n==1) move(x,z);//如果只有一个盘子,则直接将盘子转移到最后需要转移到达的柱子
	else
	{
		hanoi(n-1, x, z, y);//先将n-1个盘子从x借助z转移到y上
		move(x,z);//转移x上第n个盘子到z上
		hanoi(n-1, y, x, z);//将y上的n-1个盘子借助x转移到z上
	}
}

假设n为圆盘的数量,T(n)为移动n个圆盘的次数

当n=1时,T(1)=1;

当n=2时,T(2)=2T(1)+1=3;

当n=3时,T(3)=2T(2)+1=7;

cxl
cxl

故n阶汉诺塔问题最少共需要2^n-1步

算法的时间复杂度为:O(2^n)

参考文章:

汉诺塔(Hanoi)问题归纳总结_hanoi问题__坐看云起时_的博客-CSDN博客

【精选】汉诺塔(hanoi)问题从0到1详解_汉诺塔问题-CSDN博客

懒猫老师-C语言-汉诺塔问题详解(hanoi)_哔哩哔哩_bilibili

递归的一些基本的理解(个人)-CSDN博客

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值