关于繁衍类问题

经典题:兔子繁衍问题

一对兔子,从出生后第3个月起每个月都生一对兔子。小兔子长到第3个月后每个月又生一对兔子。
第一类问法:假如兔子都不死,请问第1个月出生的一对兔子,到第N个月,一共有多少对兔子?
第二类问法:假如兔子都不死,请问第1个月出生的一对兔子,至少需要繁衍到第几个月时兔子总数才可以达到N对?

这类问题本质其实还是问第i个月有多少对兔子
其实问题本身不难,经典兔子繁衍问题也符合斐波那契数列,所以也可以用斐波那契数列去做。
但如果用实际思路去做:我们可以把每一个月分步进行,成长,(找出)长大的,繁衍下一代。

由此可得代码。

#include <stdio.h>
int main(void)
{
    int n;
    scanf("%d",&n);
    int big_rabbit=0;//对 
    int small_rabbit[3]={1,0,0};//对
    while(--n)
    {
        //成长
        small_rabbit[2]=small_rabbit[1];
        small_rabbit[1]=small_rabbit[0];
        //已经长大的了
        big_rabbit+=small_rabbit[2];
        //繁衍
        small_rabbit[0]=big_rabbit;
    }
    printf("%d",big_rabbit+small_rabbit[0]+small_rabbit[1]);
    return 0;
}

进阶题:母牛的故事 (HUD-2018)

题目链接:母牛的故事
有一头母牛,它每年年初生一头小母牛。每头小母牛从第四个年头开始,每年年初也生一头小母牛。请编程实现在第n年的时候,共有多少头母牛?

和上题比较,变动就在从3个月变成4个月了。因此不满足斐波那契数列。
但问题本质还是一样,实际思路依旧可以轻松解决

#include <stdio.h>
int main(void)
{
    int n;
    while(scanf("%d",&n),n!=0)
    {
        if(n<=4)
            printf("%d",n);
        else
        {
            //3 lcow 1 cow
            n-=4;
            //这里把第四年作为开端,下面思路如出一辙
            int cow=1,lcow[4]={1,1,1,0};
            while(n--)
            {
            	//长大
                lcow[3]=lcow[2];
                lcow[2]=lcow[1];
                lcow[1]=lcow[0];
                //成年
                cow+=lcow[3];
                //繁衍
                lcow[0]=cow;
            }
            printf("%d",cow+lcow[0]+lcow[1]+lcow[2]);
        }
        printf("\n");
    }
    return 0;
}

当然这些题也可以通过数学归纳法整理出递推公式
f(n)=f(n-1)+f(n-3) //n>=4
然后利用递推公式去求解。

偏现实问题:动物繁衍问题

设农场饲养某种动物所能达到最大年龄为15岁,分三个年龄段:
一.1~5岁
二.6~10岁
三.11~15岁
动物从第二个年龄段开始繁衍后代,第二个年龄段可以繁衍四个后代,第三个年龄段可以繁衍3个后代
第一个年龄段和第二个年龄段的动物能顺利进入下一个年龄段的存活率分别为0.5和0.25

假设农场现有三个年龄段的动物各1000头.(假设都是各年龄段的初始岁数即1岁6岁11岁各1000)
(1).计算5年后,10年后,15年后,20年后各年龄段动物数量,50年后农场三个年龄段的动物情况如何?

按照实际思路代码:

#include <stdio.h>
void P_sum(int);
int main()
{
    P_sum(5);
    P_sum(10);
    P_sum(15);
    P_sum(20);
    P_sum(50);
    return 0;
}
void P_sum(int n)
{
    int n_t=n;
    long long animal[3][5]=\
    {
    {1000,0,0,0,0},\
    {1000,0,0,0,0},\
    {1000,0,0,0,0}
    };
    while(n--)
    {
        //成长+死亡
        long long animal0=animal[0][4];
        long long animal1=animal[1][4];
        for(int i=0;i<3;i++)
        {
            for(int j=3;j>=0;j--)
                animal[i][j+1]=animal[i][j];
        }
        //成年(跨年龄段)
        animal[1][0]=animal0/2;
        animal[2][0]=animal1/4;
        //繁衍
        long long sum_animal=0;
        for(int i=0;i<4;i++)
            sum_animal+=animal[1][i]*4+animal[2][i]*3;
        animal[0][0]=sum_animal;
    }
    long long sum=0;
    for(int i=0;i<3;i++)
        for(int j=0;j<5;j++)
            sum+=animal[i][j];
    printf("%d years later :%lld\n",n_t,sum);
    if(n_t==50)
        printf("1.%lld\n2.%lld\n3.%lld",animal[0][0]+animal[0][1]+animal[0][2]+animal[0][3]+animal[0][4],\
        animal[1][0]+animal[1][1]+animal[1][2]+animal[1][3]+animal[1][4],\
        animal[2][0]+animal[2][1]+animal[2][2]+animal[2][3]+animal[2][4]);
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值