目录
问题背景
假设农场中有一头母牛,它从第4年开始每年生一头小牛,且每头小牛也是母牛,同样从第4年开始每年生一头小牛。问第 i
年农场中有多少头牛。
递推公式的逻辑
-
定义状态:
-
dp[i]
表示第i
年农场中牛的总数。
-
-
递推关系:
-
第
i
年的牛的数量由两部分组成:-
dp[i - 1]
:表示第i-1
年的牛的数量。这些牛在第i
年仍然存在。 -
dp[i - 4]
:表示第i-4
年的牛的数量。这些牛在第i-4
年出生,到第i
年时已经满4岁,可以生育新的小牛。
-
-
因此,第
i
年的牛的总数等于第i-1
年的牛的数量加上第i-4
年的牛的数量。
-
-
递推公式:
dp[i]=dp[i−1]+dp[i−4]dp[i]=dp[i−1]+dp[i−4]
递推公式的推导
-
基本情况:
-
第1年:只有1头母牛,
dp[1] = 1
。 -
第2年:仍然只有1头母牛,
dp[2] = 1
。 -
第3年:仍然只有1头母牛,
dp[3] = 1
。 -
第4年:母牛开始生小牛,
dp[4] = 2
(1头母牛 + 1头小牛)。
-
-
递推过程:
-
第5年:
dp[5] = dp[4] + dp[1] = 2 + 1 = 3
。 -
第6年:
dp[6] = dp[5] + dp[2] = 3 + 1 = 4
。 -
第7年:
dp[7] = dp[6] + dp[3] = 4 + 1 = 5
。 -
第8年:
dp[8] = dp[7] + dp[4] = 5 + 2 = 7
。
-
动态规划的实现
以下是使用动态规划实现该递推公式的代码:
#include <stdio.h>
int countCows(int n) {
if (n <= 0) return 0;
if (n == 1 || n == 2 || n == 3) return 1;
if (n == 4) return 2;
int dp[n + 1]; // 动态规划数组
dp[0] = 0; // 第0年没有牛
dp[1] = 1; // 第1年有1头牛
dp[2] = 1; // 第2年有1头牛
dp[3] = 1; // 第3年有1头牛
dp[4] = 2; // 第4年有2头牛
// 填充动态规划数组
for (int i = 5; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 4]; // 递推公式
}
return dp[n]; // 返回第n年的牛的数量
}
int main() {
int years = 20;
int totalCows = countCows(years);
printf("%d年之后共有%d头牛\n", years, totalCows);
return 0;
}
示例输出
输入:
years = 20
输出:
20年之后共有345头牛
总结
-
递推公式
dp[i] = dp[i - 1] + dp[i - 4];
的逻辑是基于牛的繁殖规则:第i
年的牛的数量等于第i-1
年的牛的数量加上第i-4
年的牛的数量。 -
动态规划通过存储中间结果避免了重复计算,显著提高了效率。
-
该递推公式适用于类似的递推问题,如动物的繁殖、资源的增长等。