运用函数递归解决汉诺塔、青蛙跳台问题以及青蛙跳台潜在问题

一、汉诺塔

汉诺塔又称河内塔,起源于印度,传说大反天创造世界时做了三根金刚石柱,其中一根柱子上落着六十四片黄金圆盘。大反天命令陀螺门将圆盘按大小顺序重新摆放到另一根柱子上,规定每次只能移动一块,并且大圆盘不能放到小圆。


#include<stdio.h>
int count;
void move(char a, char b, char c, int n)
{
	if (n == 1)
	{
		++count;
		printf("第%d次移动:将现在%c上的第一个圆盘移到%c\n",count,a,c);
	}
	else if (n > 1)
	{
		move(a, c, b, n - 1);//通过c柱子将a柱子上n-1个圆盘移到b
		++count;
		printf("第%d次移动:将现在%c上的第一个圆盘移到%c\n",count, a, c);
		move(b, a, c, n - 1);//看下文绿色字体解释
	}
}

int main()
{
	int n;
	scanf("%d", &n);
	move('a','b','c', n);
	return 0;

}

8ab4ff0a6c5d4bff847037de6fbaa457.png
 


现在我们看下图进行解析3d5cb3ae48254f4f865cfff03d50d053.png091f139b053e45a9b8e8e73dbbd499ba.png经过这样移动便可将n-1个圆盘移动到b上,这个过程通过代码实现便是上面的:

move(a, c, b, n - 1);

然后将a上最后一个圆盘移到。然后得到下图:ef66c5120c01457d919d160e59bf494d.png


这时我们发现a是空的,b是有2个圆盘,c上有一个最大的圆盘因为其不影响任何其他圆盘放在c上所以我们可以假设c没有圆盘,如果我们把a当作b,b当作a是不是就相当于刚开始n为2个圆盘,故此我们在调用一次函数即递归,代码实现便是move(b, a, c, n - 1);至此函数不断递归下去直到

n-1为1时函数结束!!!这便是递归解决汉诺塔问题了!!!

二、青蛙跳台

青蛙跳台阶问题是一个经典的数学问题,其内容为:一只青蛙一次可以跳上一级台阶或两级台阶,问青蛙从第n级台阶跳上第n+1级台阶,总共有多少种跳法。


下面看一下代码实现:

#include<stdio.h>
int dancestep(int n)
{
	if (n == 1)
	{
		return 1;//当只有一层台阶时有一种跳法
	}
	if (n == 2)
	{
		return 2;//当只有2层台阶时有两种跳法
	}
	if (n > 2)   //n大于二时进行递归运算
	{
		return dancestep(n - 1) + dancestep(n - 2);
	}
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int num = dancestep(n);
	printf("%d\n", num);
	return 0;
}

接下来我们进行分析:

假设青蛙从第n级台阶跳上第n+1级台阶的跳法数为f(n),那么当它只跳一级时,就可以从第n-1级台阶跳上第n级台阶,此时跳法数为f(n-1);当它一次跳两级时,就可以从第n-2级台阶跳上第n级台阶,此时跳法数为f(n-2)。
因此,我们可以得到递推公式:f(n)=f(n-1)+f(n-2)。
根据这个递推公式,我们可以依次计算出从第1级台阶到第n级台阶的所有跳法数。例如,当n=3时,有f(3)=f(2)+f(1)=2+1=3种跳法。
需要注意的是,青蛙跳台阶问题还有其他的变种,例如每次只能跳一级或者每次只能跳两级,但是其本质都是相同的,都可以使用递归的方法来解决。

注:递归虽然代码看着简便但n如果稍微大一点时电脑的计算次数的计算量却非常大

至于为什么看下图:

acdea86dad2743c883e611a6536be989.png


我们假设n=40由此我们看出当函数需要进行的计算量(n-1)^2,故此我们其实也可以用普通循环的方法来解决青蛙跳台阶的问题。下面展示代码:

#include<stdio.h>
int main()
{
	int a=1, b=2,i,n,sum;
	scanf("%d", &n);
	if (n >= 3)
	{
		for (i = 1; i <= n - 2; i++)
		{
			sum = a + b;
			a = b;
			b = sum;
		}
	}
	else
	{
		sum = n;
	}
	printf("%d", sum);
	return 0;
}

这样计算的代码就不会在n较大时使函数的计算量成指数增长了!!!

好了各位今天的博客就结束了!!!

9a164d6e34854d59801239ac381a7c11.png

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值