递归巧解古印度汉诺塔问题

举报
未见花闻 发表于 2022/08/31 22:24:01 2022/08/31
【摘要】 汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。汉罗塔问题背景介绍汉诺塔问题,是心理学实验研究常用的任务之一。该问题的主要材料包括三根高度相同的柱子和一些大...

汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

汉罗塔问题背景介绍
汉诺塔问题,是心理学实验研究常用的任务之一。该问题的主要材料包括三根高度相同的柱子和一些大小及颜色不同的圆盘,三根柱子分别为起始柱A、辅助柱B及目标柱C。
相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。(摘自百度百科)
在这里插入图片描述

从上面的资料我们可以提取出一个问题:
Hanoi(汉诺)塔问题。古代有一个梵塔,塔内有3个座A,B,C。开始时A座上有64个盘子,盘子大小不等,大的在下,小的在上。有一个先知想把这64个盘子从A座移到C座,但规定每次只允许移动一个盘,且在移动过程中在3个座上都始终保持大盘在下,小盘在上。在移动过程中可以利用B座。你能帮这位先知实现他的想法吗?要求编程序输出移动盘子的步骤。
解题思路:
这位先知会这样想: 假如有另外一位先知能有办法将上面63个盘子从A座移到B座。那么,问题就解决了。此时先知只须这样做:
① 联系他的好朋友第2个先知将63个盘子从A座移到B座;
② 自己将1个盘子(最底下的、最大的盘子)从A座移到C座;
③ 再让第2个先知将63个盘子从B座移到C座。
第2个先知又想: 如果有人能将62个盘子从一个座移到另一座,我就能将63个盘子从A座移到B座,他是这样做的:
① 联系他的好朋友第3个先知将62个盘子从A座移到C座;
② 自己将1个盘子从A座移到B座;
③ 再让第3个先知将62个盘子从C座移到B座。
……
以此类推
在这里插入图片描述
为了便于理解,我们将盘子数量降低到3个,所以首先分析将A座上3个盘子移到C座上的过程:
在这里插入图片描述

① 将A座上2个盘子移到B座上(借助C座)。
在这里插入图片描述

② 将A座上1个盘子移到C座上。
在这里插入图片描述

③ 将B座上2个盘子移到C座上(借助A座)。
在这里插入图片描述

其中第②步可以直接实现。第①步又可用递归方法分解为:

  1. 将A座上1个盘子从A座移到C座;
  2. 将A座上1个盘子从A座移到B座;
  3. 将C座上1个盘子从C座移到B座。

第③步可以分解为:

  1. 将B座上1个盘子从B座移到A座上;
  2. 将B座上1个盘子从B座移到C座上;
  3. 将A座上1个盘子从A座移到C座上。

将以上综合起来,可得到移动3个盘子的步骤为:
A→C,A→B,C→B,A→C,B→A,B→C,A→C。
共经历7步。由此可推出: 移动n个盘子要经历(2^n^-1)步。

由上面的分析可知: 将n个盘子从A座移到C座可以分解为以下3个步骤:
① 将A座上n-1个盘借助C座先移到B座上;
② 把A座上剩下的一个盘移到C座上;
③ 将n-1个盘从B座借助于A座移到C座上。

可以把上面3个步骤分成两类操作:
① 将n-1个盘从一个座移到另一个座上(n>1)。这就是先知让他的朋友第2个先知做的工作,它是一个递归的过程,即先知将任务层层下放,直到第64个先知为止。——hanoi函数
② 将1个盘子从一个座上移到另一座上。这是先知自己做的工作。——move函数

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

/*Hanoi(汉诺)塔问题。古代有一个梵塔,塔内有3个座A,B,C。
开始时A座上有64个盘子,盘子大小不等,大的在下,小的在上。
有一个先知想把这64个盘子从A座移到C座,但规定每次只允许移动一个盘,
且在移动过程中在3个座上都始终保持大盘在下,小盘在上。
在移动过程中可以利用B座。你能帮这位先知实现他的想法吗?
要求编程序输出移动盘子的步骤。*/

void hanoi(int n, char a, char b, char c);////定义hanoi函数
//将n个盘从a座借助b座,移到c座 
void move(char x, char y);

int main()
{
	int lay = 0;
	scanf("%d", &lay);
	hanoi(lay, 'A', 'B', 'C');//输入盘子个数

	//最终输出移动方案
	return 0;
}
void move(char x, char y)
{
	printf("%c->%c\n", x, y);
}
void hanoi(int n, char a, char b, char c)
{
	if (n == 1)
		move(a, c);
	else
	{
		hanoi(n - 1, a, c, b);//借c将a移动至b
		move(a, c);
		hanoi(n - 1, b, a, c);//借a将b移动至c
	}

}

根据这个代码让我们来运行一下我们举过移动三个圆盘的例子。
在这里插入图片描述
一共7步,与我们举例得出的结果一致。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。