题目解析
题目:有一对兔子,从出生后第4个月起每个月都生一对兔子,小兔子长到第4个月后每个月又生一对兔子,假如兔子都不死,问某个月后的兔子总数为多少对?
我先统计一下8个月内兔子的情况,一个月是小兔,两个月中兔,三个月大兔,四个月成兔(开始生兔子),情况如下表:
月份 | 小 | 中 | 大 | 成 | 总数 |
---|---|---|---|---|---|
1 | 1 | 0 | 0 | 0 | 1 |
2 | 0 | 1 | 0 | 0 | 1 |
3 | 0 | 0 | 1 | 0 | 1 |
4 | 1 | 0 | 0 | 1 | 2 |
5 | 1 | 1 | 0 | 1 | 3 |
6 | 1 | 1 | 1 | 1 | 4 |
7 | 2 | 1 | 1 | 2 | 6 |
8 | 3 | 2 | 1 | 3 | 9 |
在写这个递归之前我并没有上网看思路、看代码,而是自己想了半小时吧,然后写出来了,不是很熟递归。。见谅
递归思路
公式化的递归公式很容易搜到。
比如三个月生一对就是F(n)=F(n-1)+F(n-2)
四个月生一对就是F(n)=F(n-1)+F(n-3)
但是,知道公式,我们更应该知道为什么?
从汉诺塔递归公式中我明白递归的函数之间其实就是各管各的,每个多胞胎兄弟们都把自己的事情做好,那么整件事也就全做好了。
在这个问题中有两个双胞胎兄弟(就是一样的函数),大哥只管最开始的那对兔子(只管这对兔子生了多少,不管这对兔子生的孩子长大后生了多少)。
二弟呢?二弟就是只管大哥那对兔子生下的孩子,这二弟管的孩子和大哥那对兔子其实是一样的(一样会长大,一样会生孩子)。
子又生孙,孙又生子(就出现了无数个不同层数的大哥,不同层次的二弟)。
代码:
#include <stdio.h>
int bornRabbit(int month)
{
int sum = 0;
if (month < 4)
{
return month == 0 ? 0 : 1;
}
else
{
//第4个月生兔子,记录新生的兔子的数量
month-=3;
sum=bornRabbit(month);//计录孩子生了多少
//加回月数,算出最开始那只兔子下一月的生孩子情况
month+=3;
return sum+bornRabbit(month-1);//加上最初的兔子生的数量
}
//其实,每个函数,每个大哥或二弟,不是都是只管一只兔子吗?
}
int main()
{
printf("%d\n", bornRabbit(8));
return 0;
}
这是便我最开始写的递归,不是很简练,但应该较为容易理解。
简练代码:
int f(int m)
{
if (m < 4)
return month == 0 ? 0 : 1;
return f(m-1)+f(m-3);
}
以上,结束。(可能以后会将递归讲的更清楚吧 捂脸)