C/C++经典习题—汉诺塔

一、题目

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

二、解题思路

        题目简单来说就是将A柱上面的所有盘子借助B柱移动到C柱上,每次移动一个盘子并且大盘子在小盘子下面。我们可以先从简单的问题入手,比如我们最开始放三个盘子在A柱上面,那么我们需要移动的步骤就是:

        将编号为1的盘子直接从A柱子移到C柱子
        将编号为2的盘子直接从A柱子移到B柱子
        将编号为1的盘子直接从C柱子移到B柱子
        将编号为3的盘子直接从A柱子移到C柱子
        将编号为1的盘子直接从B柱子移到A柱子
        将编号为2的盘子直接从B柱子移到C柱子
        将编号为1的盘子直接从A柱子移到C柱子

        乍一看你会觉得,怎么三个盘子就这么多步骤啊,那要是64个盘子岂不是代码老长了。别慌,既然能成为经典问题那就肯定有惊为天人的简洁代码令你耳目一新。我们仔细看上面的例子,发现每一次移动都有一定的规律,那我们就可以用递归的思想来解决这个问题。有的友友一听到递归就头大,没办法,慢慢来吧,递归思想的重要性随着学习的深入,体会会越来越深,也越能感受到他的精妙之处。

三、代码分析

        按照上面的思路,要用到递归函数,那么这个函数的参数是什么呢?经过分析我们不难发现,首先要传一个整形n用来表示“将编号为n的盘子”移来移去,另外还需要三个字符参数‘A’,'B','C'来表示每次从哪根柱子移动到哪根柱子。这样我们就确定了递归函数需要的四个参数,可以定义出递归函数     void f(int n,char A,char B,char C)

        而递归函数需要两个条件,一是存在限制条件,二是每次递归后都越来越接近这个限制条件。那么我们需要看一下这个问题的限制条件是什么?

        不难发现,当n=1时,可以直接把这一个盘子从 C 柱移动到 C 柱,这就是限制条件。

        那么他该怎么样递归呢?

        经过上面的分析我们知道,每次移动都是从 A 柱借助 B 柱移动到 C 柱,注意,这里的 A B C柱是形参,不是实际的A B C 柱。是不是不太好理解?我们定义的函数是 void f(int n,char A,char B,char C) ,这里的A B C柱是形参,把它理解为1号柱,2号柱,3号柱,最开始他们的名字分别是A柱,B柱,C柱,每次递归之后,1号柱可能就不叫 A 柱了,他可能叫 B 柱,也可能叫 C 柱。

        所以我们移动是从1号柱借助2号柱移动到3号柱,不用在意他们叫什么名字(还不太理解的可以仔细思考一下或者结合下面的代码理解,我不太会配图,纯文字的话可能不太好读。这个题只有这一点难理解,理解之后就解决了)。

四、代码

看完代码分析并理解了大半之后,我们来看一下代码。

#include<stdio.h>
void f(int n,char A,char B,char C)
{
	if(1==n)
		printf("将编号为%d的盘子直接从%c柱子移到%c柱子\n",n,A,C);
	else
	{
		f(n-1,A,C,B);
		printf("将编号为%d的盘子直接从%c柱子移到%c柱子\n",n,A,C);
		f(n-1,B,A,C);
	}
}

int main()
{
	char ch1='A';
	char ch2='B';
	char ch3='C';
	int n;
	printf("请输入你想放几个盘子:");
	scanf("%d",&n);
	f(n,'A','B','C');
	return 0;
}

希望有所帮助,如果文章有问题或者有描述不清楚的地方欢迎私信告知,万分感谢。 


参考文章:(抄了个题目)
https://blog.csdn.net/m0_68989458/article/details/124087487

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值