兔子繁殖问题(校内作业)
兔子繁殖问题,即斐波那契数列问题,著名意大利数学家斐波那契(Fibonacci)1202年提出一个有趣的问题。
某人想知道一年内一对兔子可以生几对兔子。他筑了一道围墙,把一对大兔关在其中。已知每对大兔每个月可以生一对小兔,而每对小兔出生后第三个月即可成为“大兔”再生小兔。问一对兔子一年能繁殖几对小兔?
对于这样一系列重叠子问题,不妨运用动态规划(Dynamic Programming)思想求出一对兔子n月能繁殖的对数。
并且进一步思考,若小兔出生后第四个月即可再生小兔呢,第m个月呢?
1⃣️ 声明长度为[1, n + 1]
的DP
数组,dp[i]
代表第i
月围墙中兔子的对数。
2⃣️ 初始化dp
,第一年为初始的1对兔子即dp[1] = 1
,第二年为上一年兔子对数加第一年兔子所生的1
对即dp[2] = 2
。
3⃣️ 观察以下规律,
可推出dp[i] = dp[i - 1] + dp[i - 2]
,当然若小兔出生后第m
个月即可再生小兔,那么dp[i] = dp[i - 1] + dp[i - m + 1]
,即第上一年已有对数加上前m
个月的兔子所生对数。
这一步骤为确定状态转移方程,即由某一状态转移到另一状态是以怎样的方式,本题属于较简单的情况,从前往后即可推得。
确定这一转移方式的意义就是利用计算机强大的算力去代替人脑每一步需要考虑的情况
从前往后遍历,dp[n]
即为所求(第n月围墙中兔子的对数)。
以下是代码实现:
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
int dp[n + 1];
dp[1] = 1;
dp[2] = 2;
for (int i = 3; i <= n; ++i) dp[i] = dp[i - 1] + dp[i - 2];
printf("%d\n", dp[n]);
return 0;
}
输入12
即为原题所求。
结果为:
本题除了运用文章中提到的动态规划思想解决,运用数学知识和函数递归同样可以得解,不过动态规划是解决一系列重叠子问题的通解,掌握和了解对于算法学习还是非常有必要的,同学们可以自行查阅动态规划相关资料。
想进一步了解动态规划的应用,请阅读博主的另外一篇文章最长公共子序列长度。
觉得博主的文章写得好的话,手动点个赞吧!