USTCOJ1373 母牛出生问题

该博客探讨了一道USTCOJ算法题,涉及一头母牛每两年生育一头母牛,五年后死亡的场景。文章介绍了两种解法:一种使用动态规划模拟牛的数量变化;另一种则是预计算并存储前50年牛的数量,以提高查询效率。博主提供了代码示例,并指出了解法二的高效性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:一头母牛从出生后,每两年可以生下一头母牛,即在第二年和第四年分别可产下一头母牛,出生后第五年将会死去。假设现在有一头牛,N年后总共有多少头牛?

链接:http://acm.ustc.edu.cn/ustcoj/problem.php?id=1373

本题有两种解法。

解法一分析如下(原文在此):

用一个大小为5的整形数组x[5]来保存牛的个数,x[i]表示当前有x[i]头年龄为i的牛。牛出生的时候为0岁,在二岁和四岁的时候生一个小牛,在五岁的时候死去。

初始只有1头0岁的牛,x[0]=1,x[1~4]=0,随后每一年,所有牛都长一岁,且2岁和4岁的牛会生一个小牛。
第一年:x[1]=1,x[2~4]=0,x[0]=0没有小牛出生。
第二年:x[1]=0,x[2]=1,x[3]=0,x[4]=0,x[0]=1,出生了1头小牛,为0岁
第三年:x[1]=1,x[2]=0,x[3]=1,x[4]=0,x[0]=0,没有小牛出生
第四年:x[1]=0,x[2]=1,x[3]=0,x[4]=1,x[0]=2,有2头小牛出生,为0岁
第五年:x[1]=2,x[2]=0,x[3]=1,x[4]=0,x[0]=0,没有小牛出生
也就是说对于每一年,今年i(i>0)岁牛的头数等于去年i-1岁牛的头数,0岁小牛的头数等于今年年2岁和4岁牛的头数之和,也就是:
x[4]=x[3];
x[3]=x[2];
x[2]=x[1];
x[1]=x[0];
x[0]=x[2]+x[4];
最终x[0~4]之和就是所有牛的头数。
代码如下:

#include <stdio.h>
int main()
{
    int N;
    scanf("%d",&N);
    int x[5]={1,0,0,0,0};
    for (int i=1;i<N+1;i++)
    {
        x[4]=x[3];
        x[3]=x[2];
        x[2]=x[1];
        x[1]=x[0];
        x[0]=x[2]+x[4];
    }
    printf("%d",x[0]+x[1]+x[2]+x[3]+x[4]);
    return 0;
}

分析可知,每过一年,所有牛都增长一岁。也都由新的牛出生。在上述代码中,通过数组的赋值来模拟这一过程。但事实上,赋值操作并不是必须的。此外,上述代码并不能通过OJ,因为它只处理了一组数据。我们当然可以在外侧添加一层循环来处理多组数据。但这样效率太低,我们完全可以预先将前50年的牛总数情况计算并存储在数组中,于是计算n年后的牛的总数就变成了一个查询操作。代码如下:

/**********
*RunId: 78578
*Author: fortest
***********/
#include <cstdio>
#include <cstring>

class Cattles
{
	int x[5];
	int cur;
public:
	Cattles()
    {
        memset(x, 0, sizeof(x));
        x[0] = 1;
        cur = 4;
    }
    void increase()
    {
        x[cur] = x[(cur+4)%5] + x[(cur+2)%5];
        cur += 4;
        cur %= 5;
    }
    int getSum()
    {
        int sum = 0, i = 5;
        while (i--)
            sum += x[i];
        return sum;
    }
};

int main()
{
    Cattles cattle;
    int ans[55] = {1};
    for (int i = 1; i < 55; i++)
    {
        cattle.increase();
        ans[i] = cattle.getSum();
    }
    int n;
    while (scanf("%d", &n) != EOF)
        printf("%d\n", ans[n]);
    return 0;
}


解法二:

在稿纸上写出前14年牛的总数情况,如下:

年份    0     1     2     3     4     5     6     7     8    9    10     11     12   13     14
总数    1     1     2     2     4     3     6     5     10   8    16     13     26   21     42
观察上述数据,我们会发现,对于奇数年份,总数分别是:1、 2、 3、 5、 8、13 ....而这,恰恰就是一个Fibonacci数列。而偶数年的牛的总数,总是前一年的两倍。

了解了这一规律,那么编码就不是问题了。可参考如下代码实现:

/**********
*RunId: 74280
*Author: bairui
***********/
#include <iostream>
using namespace std;
#define MXN 50

int main()
{
    int a[MXN / 2 + 1] = {1, 2}, n;
    for (int i = 2; i <= MXN / 2; i++)
        a[i] = a[i - 1] + a[i - 2];
    while (cin >> n)
        cout << (n % 2 ? a[n >> 1] : a[(n >> 1) - 1] << 1) << endl;
    return 0;
}

### JavaScript 母牛繁殖问题算法实现 以下是基于引用中的逻辑和需求编写的 JavaScript 实现代码。该代码解决了母牛繁殖问题,其中考虑了母牛从第 4 开始每产一头新母牛的情况。 #### 解决方案描述 通过递归方法来模拟母牛的繁殖过程。核心思想是从初始状态出发,逐累加新母牛的数量,并返回最终的结果。具体实现如下: ```javascript function calculateCows(year) { let cows = []; // 存储每一母牛龄列表 if (year < 1) return 0; // 初始化第一母牛 cows.push(1); for (let currentYear = 2; currentYear <= year; currentYear++) { const newborns = cows.filter(age => age >= 4 && age < 15).length; // 计算当前份能够产的母牛数量 cows.forEach((_, index) => cows[index] += 1); // 所有母牛龄增加一岁 // 添加新母牛 Array.from({ length: newborns }).forEach(() => cows.push(1)); // 移除超过寿命的母牛(如果存在) cows = cows.filter(age => age <= 20); } return cows.length; // 返回总母牛数量 } // 测试函数 console.log("第13共有:" + calculateCows(13)); // 输出结果 ``` --- #### 关键点解析 1. **初始化** 初始状态下只有一头母牛,其龄为 `1` 岁[^1]。 2. **逐更新** 随着时间推进,程序逐一处理每一头母牛龄增长情况,并判断哪些母牛具备产能力[^2]。 3. **过滤条件** 只有当母牛达到 4 岁及以上且未满 15 岁时才具有育能力[^3]。此外,任何超过 20 岁的母牛会被移除。 4. **性能优化** 使用数组存储所有母牛龄信息,便于动态调整并支持复杂的筛选逻辑[^4]。 --- #### 示例运行结果 对于输入 `calculateCows(13)`,输出应为: ``` 第13共有:872 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值