(递推1)兔子繁殖问题

时间:2023-01-17 11:24:07

有一对小兔子,小兔子过Z个月长大,一对大兔子X个月生Y对小兔子,求n个月后的兔子总对数。
当xyz都是1的时候,f(n)=f(n-1)+f(n-2)
问题一:
有一对小兔子,小兔子过5个月长大,一对大兔子3个月生4对小兔子,求n个月后的兔子总对数。
f(n)表示n个月后的兔子总数
f(n)=n那个月原有的兔子+n那个月新生的兔子
n那个月原有的兔子是:f(n-1)
n那个月新生的兔子是:n-x那个月成熟的兔子,也就是n-x-z那个月所有的兔子,因为n-x-z那个月所有的兔子在n-x那个月的时候都成熟了

故f(n)= f(n-1)+ f(n-x-z) * (y/x);这里必须是* (y/x),这是每个月生产的。(那个月成熟的兔子在一个月里生的小兔子的个数)

这个表达式也适合于一个月生一对的情况;
一个月的情况可以看成成熟+不成熟,和原来的+新生的。而多个月的情况看成后一种比较好,因为看成前一种会超级麻烦。

到本题,也就是f(n)= f(n-1)+ f(n-8)*(4/3);

问题二:
有一对小兔子,小兔子过5个月长大,一对大兔子3个月生4对小兔子,求n个月后的大兔子总对数。
f(n)表示大兔子,那么
f(n)= 上个月的大兔子数+这个月新长成的大兔子数
上个月的大兔子数是:f(n-1)
这个月新长成的大兔子数是:因为兔子需要5个月长大,所以应该是n-5个月那个月的新出生的兔子,
n-5个月那个月的新出生的兔子是n-5-3那个月的所有大兔子数,因为大兔子经过三个月才能有小兔子,
故f(n)=f(n-1)+f(n-5-3)*(4/3);

#include <iostream>
using namespace std;
//前八个月的兔子总对数都是一对,initTotalRabbit[1]表示第一个月 
double initTotalRabbit[9]={0,1,1,1,1,1,2.3333,3.6667,5};
double calcTotalRabbit(int n){
    if(n<=8)
        return initTotalRabbit[n];
    else
        return calcTotalRabbit(n-1)+ calcTotalRabbit(n-8)*(4.0/3);
} 

//前五个月的大兔子数目为0,initBigRabbit[1]表示第一个月的大兔子数目
double initBigRabbit[9]={0,0,0,0,0,0,1,1,1};
double calcBigRabbit(int n){
    if(n<=8)
        return initBigRabbit[n];
    else
        return calcBigRabbit(n-1)+ calcBigRabbit(n-5)*(4.0/3);
} 
int main(){
    for(int i=1;i<=20;i++){
        double total=calcTotalRabbit(i);
        double big=calcBigRabbit(i);
        printf("月份:%3d 兔子总对数:%6.2lf 大兔子对数:%6.2lf 小兔子对数:%6.2lf\n",i,total,big,total-big);
    }

    return 0;
}