题目描述
有一头母牛,它每年年初生一头小母牛。每头小母牛从第四个年头开始,每年年初也生一头小母牛。请编程实现在第n年的时候,共有多少头母牛?
输入格式
输入数据由多个测试实例组成,每个测试实例占一行,包括一个整数n(0<n<55),n的含义如题目中描述。
n=0表示输入数据的结束,不做处理。
输出格式
对于每个测试实例,输出在第n年的时候母牛的数量。
每个输出占一行。
样例输入
2
4
5
0
样例输出
2
4
6
求解代码
我的代码
#include <iostream>
using namespace std;
typedef long long ll;
ll cownum(ll year,ll n,ll m){
ll sum=0;
if(year<=4){//当年份小于等于4时,小母牛数量就等于年份-1
m+=year-1;
}else{//大于4时,用year-4递归求母牛的数量。
//在每次递归中会返回每次递归的母牛总数量,包括了母牛和小母牛。
//要注意的时,递归一次n就要+4,因为年份-4,即新增了4头小母牛
n+=cownum(year-4,n,m)+4;
}
sum=n+m;//总数的母牛n+小母牛m
return sum;
}
int main()
{
ll year;
cin>>year;
long long int count=0;//计数
while(year){
count=cownum(year,1,0);
cout<<count<<endl;
cin>>year;
}
return 0;
}
使用递归实现,计算第n年共有多少头母牛时调用函数 cownum()
。若年份小于等于4,则累加每一年产生的小母牛数量;否则递归计算前四年的母牛和小母牛数量,然后再加上第n-4年至第n年产生的所有母牛和小母牛的数量。
缺点:这种算法的时间复杂度为指数级,当 n 很大时计算时间会非常长。
优化代码(动态规划)
#include<iostream>
using namespace std;
long long cow[56] = {0,1,2,3,4}; // 在main函数外定义的数组会全部自动初始化为0
long long fab(int month) {
if(cow[month] == 0) { // 没有算过的月份,数组内存的是0
cow[month] = fab(month-1) + fab(month-3);
return cow[month];
} else {
return cow[month];
}
}
int main () {
int n;
while(scanf("%d", &n) && n) cout << fab(n) << endl;
return 0;
}
使用动态规划实现,在 main()
函数外定义一个数组 cow
用来存储第1年到第55年每一年的母牛数量。由于第i年的母牛数量只与第 i-1 年和第 i-3 年的母牛数量有关,因此可以通过递推计算出所有需要的年份的母牛数量。
优点:这种算法的时间复杂度为线性级,计算速度更快。
对比
1.我的代码使用了递归算法,而第二个代码使用了动态规划算法。
2.我的代码没有对数组进行预处理,而是在递归计算中对每一年的母牛和小母牛数量进行了很多次重复计算;而第二个代码在 main()
函数外预处理了所有年份的母牛数量,避免了重复计算。
3.第一个代码使用了typedef定义long long为ll,方便在代码中多次使用;第二个代码直接使用了long long类型。
根据题目要求,两个代码在计算时都能得到正确的结果,但在时间效率和代码实现复杂度上有所不同。
递推求解
递推求解是利用第i年母牛的数量只与第i-1年和第i-3年的母牛的数量有关
故可以直接用递推求解
#include<iostream>
using namespace std;
int main () {
int cow[56] = {0,1,2,3,4};
for(int i = 4; i < 55; i ++) cow[i] = cow[i-1] + cow[i-3];
int n;
while(scanf("%d", &n) && n) cout << cow[n] << endl;
return 0;
}
ChatGPT对“第i年母牛的数量只与第i-1年和第i-3年的母牛的数量有关”的解释是这样的:
根据题目描述,每一头小母牛从第四年开始每年都能生出一头小母牛,因此四年后的某一时刻,我们需要计算所有小母牛的数量,也就是第i年的母牛数量。
在第i-3年时,由于之前的所有小母牛都已经成熟了,可以生出新的小母牛。假设第i-3年有x头母牛,它们分别在第i-1年、第i年和第i+1年分别生下y1、y2、y3头小母牛,则第i年的母牛数量为x+y1,第i+1年的母牛数量为x+y1+y2,第i+2年的母牛数量为x+y1+y2+y3。
以上推导可以用一个方程表示:第i年的母牛数量 = 第i-1年的母牛数量 + 第i-3年的母牛能生的小母牛数量。由此可知,第i年的母牛数量只与第i-1年和第i-3年的母牛数量有关系,而与i-2年以及i-4年及更早的时间无关。
基于上述推论,我们可以运用动态规划算法来解决这个问题,避免使用递归算法需要进行很多次的重复计算,提高程序效率。