汉诺塔和青蛙跳台阶(递归函数的应用)
1. 汉诺塔
- 从数学角度来看
如下图所示,从左到右有A、B、C三根柱子,其中A柱子上面有从小叠到大的n个圆盘,现要求将A柱子上的圆盘移到C柱子上去,期间只有一个原则:一次只能移到一个盘子且大盘子不能在小盘子上面,求移动的步骤和移动的次数
(1)n == 1
第1次 1号盘 A---->C sum = 1 次
(2) n == 2
第1次 1号盘 A---->B
第2次 2号盘 A---->C
第3次 1号盘 B---->C sum = 3 次
(3)n == 3
第1次 1号盘 A—->C
第2次 2号盘 A—->B
第3次 1号盘 C—->B
第4次 3号盘 A—->C
第5次 1号盘 B—->A
第6次 2号盘 B—->C
第7次 1号盘 A—->C sum = 7 次
不难发现规律:1个圆盘的次数 2的1次方减1
2个圆盘的次数 2的2次方减1
3个圆盘的次数 2的3次方减1
。 。 。 。 。
n个圆盘的次数 2的n次方减1
故:移动次数为:2^n - 1
算法:
实现这个算法可以简单分为三个步骤:
(1) 把n-1个盘子由A 移到 B;
(2) 把第n个盘子由 A移到 C;
(3) 把n-1个盘子由B 移到 C
代码如下:
#include <stdio.h>
#include <math.h>
void Heneita(int n, char a, char b, char c)
{
int num = 0;
if (n==1)
{
printf("%c-->%c\n", a, c);
}
else
{
Heneita(n - 1, a, c, b);
Heneita(1, a, b, c);
Heneita(n - 1, b, a, c);
}
}
int main()
{
int n = 0;
scanf("%d", &n);
Heneita(n,'A','B','C');
printf("%d\n", (int)pow(2, n) - 1);
return 0;
}
运行结果:
2.青蛙跳台阶
问题1:一只青蛙一次可以跳上1个台阶,也可以跳上2个台阶。求青蛙跳上n级台阶总共有多少种跳法?
分析:这个问题从前往后分析太过复杂,不妨换个思路,如果青蛙想跳上第n个台阶,就只有两种跳法:从第n-1个台阶跳上来或者从第n-2个台阶跳上来。这样我们就可以先算第n个台阶的跳法然后用递归往下推算。第n个台阶:f(n)=f(n-1)+f(n-2);第一个台阶:f(n)=1;第二个台阶:f(n)=2;发现这个其实是斐波那契数列,如此就简单了。
规律如下图:
代码如下:
#include <stdio.h>
int jump(int n)
{
if (n <= 0)
{
printf("输入错误\n");
return 0;
}
else if (n == 1 || n == 2)
{
return 1;
}
else if (n > 2)
{
return jump(n - 1) + jump(n - 2);
}
}
int main()
{
int n = 0;
int ret = 0;
scanf("%d", &n);
ret = jump(n);
printf("%d\n", ret);
return 0;
}
运行结果:
问题2:每次可以跳1–n个台阶,跳上n个台阶有多少中跳法;
分析:同样从后往前分析,跳上第n个台阶有n-1中可能。从第一个台阶直接跳上第n个台阶……………….从第n-1个台阶跳上第n个台阶,一共有:
f(n)=f(n-1)+f(n-2)+f(n-3)+………f(1);
f(n-1)=f(n-2)+f(n-3)+………..f(1);
…………………………………………
…………………………………………..
f(n)=2f(n-1)=4f(n-2)=8f(n-3)=………..=(2^(n-1))f(1);
f(n)=2f(n-1);
f(1)=1;- 代码如下:
#include <stdio.h>
#include <math.h>
int jump(int n)
{
if (n <= 0)
{
printf("输入错误\n");
return 0;
}
else
{
return pow(2, n-1);
}
}
int main()
{
int n = 0;
int ret = 0;
scanf("%d", &n);
ret=jump(n);
printf("%d\n", ret);
return 0;
}
#include <stdio.h>
int jump(int n)
{
if (n <=0)
{
printf("输入错误\n");
return 0;
}
if (n==1)
{
return 1;
}
else
{
return 2*jump(n-1);
}
}
int main()
{
int n = 0;
int ret = 0;
scanf("%d", &n);
ret = jump(n);
printf("%d\n", ret);
return 0;
}
- 运行结果: