用递归求解汉诺塔问题

    问题描述:古代有一座梵塔,塔内有3个座A、B、C。开始时A座上有64个盘子,盘子大小不等,大的在下,小的在上。有一个老和尚想把这64个盘子从A座移到C座,但每次只允许移动一个盘,且在移动过程中在3个座上都始终保持大盘在下,小盘在上。在移动过程中可以利用B座,要求编程打印出移动的步骤。

程序设计分析:将n个盘子从A座移到C座可以分解为以下3个步骤。

  1. 将A座上n-1个盘借助C座先移到B座上。
  2. 把A座上剩下的一个盘移到C座上。
  3. 将n-1个盘从B座借助于A座移到C座上。

假设现在A座上有3个盘子,从上到下分别编号为1、2、3。如果想将A座上3个盘子移到C座上,可以分解为以下3步。

(1)将A座上2个盘子移到B座上(借助C)。(1号、2号)

(2)将A座上1个盘子移到C座上。(3号)

(3)将B座上2个盘子移到C座上(借助A)。(1号、2号)

第(1)步又可以用递归方法分解为

1.1将A上1个盘子从A移到C。(1号)

1.2将A上1个盘子从A移到B。(2号)

1.3将C上1个盘子从C移到B。(1号)

第(3)步可以分解为

3.1将B上1个盘子从B移到A上。(1号)

3.2将B上1个盘子从B移到C上。(2号)

3.3将A上1个盘子从A移到C上。(1号)

将以上综合起来,可得到移动3个盘子的步骤为:

A—>C,A—>B,C—>B,A—>C,B—>A,B—>C,A—>C

总共是2的3次方后减1,即7步。

#include<stdio.h>
#include<math.h>
void main()
{
	void hanoi(int n, char one, char two, char three);   /*对hanoi函数的声明*/
	int m,n;     /*定义整型变量m(盘子数),n(移动步数)*/
	printf("请输入盘子数:");
	scanf_s("%d", &m);
	printf("移动%d个盘子的步骤是:\n", m);
	hanoi(m, 'A', 'B', 'C');
	n = pow(2, m) - 1;          /*计算全过程总共花费的步骤数*/
	printf("总共移动了%d次", n);
}
void hanoi(int n, char one, char two, char three)   
{
	void move(char x, char y);         /*对move函数的声明*/
	if (n == 1) move(one, three);
	else {
		hanoi(n - 1, one, three, two);
			move(one, three);
			hanoi(n - 1, two, one, three);   /*在盘子移动的过程中,定义了直接移动的move函数和通过中转柱间接移动的hanoi函数,再通过对全过程进行递归使问题简单化*/
	}
}
void move(char x, char y)       /*定义move函数*/
{
	printf("%c->%c\n", x, y);
}

说明:汉诺塔问题可通过二进制反映出来。采用二进制的计数方式,从右往左看,当第一位发生改变时,移动1号盘,第二位发生改变时,移动2号盘,第三位发生改变时,移动3号盘。

注意:本处的发生改变指的是在十进制数+1的情况下,二进制中的某一位实现了从0—>1的转化。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风雪心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值