已知有一对兔子,每个月可以生一对兔子,而小兔子一个月后又可以生一对小兔子(比如:2月份出生的小兔子4月份可以生育)。也就是说,兔子的对数为:第一个月1对,第二个月2对,第三个月3对,第四个月5对.....假设兔子的生育期为两年,且不死。那么问题来了,你能说出每个月的兔子数么?
输入格式:
输入一个数n,表示第n个月,1<=n<=24。
输出格式:
输出这个月兔子的数目。
输入样例:
4
输出样例:
5
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
从pta和其他平台一直都有看见这个经典的问题,今天又刷到这一题,正好来总结一下。
基础版本
int fib(int x){
if(x==1)
return 1;
if(x==2)
return 2;
return f(x-1)+f(x-2);
}
基础版本的缺点很明显,一时效率太慢,而是占内存占太大,一旦求大的月份就会爆栈。
迭代法
int fib(int x){
if(x==1)
return 1;
if(x==2)
return 2;
itn a=1,b=2,i,sum=0;
for(i=3;i<=x;i++){
sum=a+b;
a=b;
b=sum;
}
return sum;
}
迭代法的好处就很明显了,用的是循环代替了递归,提高了空间和时间的利用。用a,b两个临时变量代替前一个数和前两个数,再加到sum中求总和,接着继续将三者不断替换,完成计算。
记忆化数组
define max 999999
int a[max];
int fib(int x){
if(x==1)
return 1;
if(x==2)
return 2;
if(!a[x]){
a[x]=f(x-1)+f(x-2);
return a[x];
}
}
记忆化数组解兔子数列的本质其实是dp,一直搞不明白的一点“简单dp==递推”这个概念一直不是很明白。但是记忆化数组就避免了递归次数过多导致的爆栈,但是吧,开的全局数组又会浪费空间。
作为一个仓鼠型程序员一直想优化一下记忆化数组,但是技术受限。以后学会了优化再更新这段代码。