青训营X豆包MarsCode 兔群繁殖之谜解题思路及解答 | 豆包MarsCode AI刷题

90 阅读4分钟

前言

兔群繁殖之谜在青训营X豆包MarsCode刷题打卡中分类为动态规划算法、简单级的问题。

何为动态规划算法?

动态规划(Dynamic Programming,DP)是一种在数学、管理科学、计算机科学、经济学和生物信息学等领域中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题。

动态规划的性质
  • 最优化原理:假设问题的最优解所包括的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。

  • 无后效性:即某阶段状态一旦确定。就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响曾经的状态。仅仅与当前状态有关。

  • 有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到(该性质非动态规划适用的必要条件)

动态规划能解决的问题

零钱兑换、最长上升子序列、堆盒子、航线问题等问题。

但兔群繁殖之谜本质上也是一个经典的斐波那契数列问题,只不过稍微做了一些变形。

问题描述

生物学家小 R 正在研究一种特殊的兔子品种的繁殖模式。这种兔子的繁殖遵循以下规律:

  1. 每对成年兔子每个月会生育一对新的小兔子(一雌一雄)。
  2. 新生的小兔子需要一个月成长,到第二个月才能开始繁殖。
  3. 兔子永远不会死亡。

小 R 从一对新生的小兔子开始观察。他想知道在第 A 个月末,总共会有多少对兔子。

请你帮助小 R 编写一个程序,计算在给定的月份 A 时,兔子群体的总对数。

注意:

  • 初始时有 1 对新生小兔子。
  • 第 1 个月末有 1 对兔子:原来那对变成了成年兔子,并开始繁殖。
  • 第 2 个月末有 2 对兔子:原来那 1 对成年兔子,繁殖了 1 对新生的小兔子。
  • 从第 3 个月开始,兔子群体会按照上述规律增长。
输入

一个整数 A(1 ≤ A ≤ 50),表示月份数。

返回

一个长整数,表示第 A 个月末兔子的总对数。

测试样例
样例 1:

输入:A = 1
返回:1

样例 2:

输入:A = 5
返回:8

样例 3:

输入:A = 15
返回:987

对问题的理解

  • 初始时有一对新生小兔子。
  • 每对成年兔子每个月会生育一对新的小兔子。
  • 新生的小兔子需要一个月成长,到第二个月才能开始繁殖。
  • 兔子永远不会死亡。

确定数据结构

由于我们需要计算每个月的兔子个数,并且每个月的兔子个数依赖于前两个月的兔子个数,因此我们可以使用一个数组来存储每个月的兔子个数。

算法步骤

  • 初始化一个数组 F,其中 F[0] 和 F[1] 都为 1,因为第 0 个月和第 1 个月都只有一对兔子。

  • 从第 2 个月开始,每个月的兔子对数等于前两个月的兔子对数之和,即 F[i] = F[i-1] + F[i-2]

  • 最终返回 F[A],即第 A 个月的兔子对数。

递归与动态规划

  • 可以使用递归的方式来计算,但为了避免重复计算,可以使用记忆化递归(即动态规划)来优化。

通过以上对问题的分析与理解,我们可以得到一个初步的框架,从而将思路和框架应用于编程,得到如下代码

问题解答

vis=[False for _ in range(76)]
F=[0 for _ in range(76)]
def calc_fbi(x):
    if vis[x]==True:
        return F[x]
    if x==1 or x==0:
        return 1
    vis[x]=True
    F[x]=calc_fbi(x-1)+calc_fbi(x-2)
    return F[x]
def solution(A):
    # Edit your code here

    return calc_fbi(A)


if __name__ == "__main__":
    # Add your test cases here
    print(solution(5) == 8)
    print(solution(1) == 1)
    print(solution(15) == 987)
    print(solution(50) == 20365011074)

编程问题的思路

  • 明确问题。要清楚程序需要实现什么功能,要理解任务的目标、输入输出是什么。

  • 其次是设计算法。这是解决问题的步骤,对于复杂的程序,可能需要考虑各种情况和逻辑分支。

  • 接着是选择合适的数据结构。数据结构决定了数据如何存储和操作。如果要存储很多用户信息,可能会用到数组或者链表。

  • 然后是进行代码编写。按照选定的编程语言的语法规则,把算法和数据结构用代码实现。

  • 最后是测试与调试。运行程序,检查是否达到预期效果。如果有错误或者不符合要求的地方,要通过调试来找出问题所在,修改代码,直到程序正确运行。