动态规划在兔子繁殖问题中的应用 |豆包MarsCode AI刷题

127 阅读3分钟

动态规划在兔子繁殖问题中的应用

这个问题本质上是一个斐波那契数列的变种,规律如下:

  • 第 1 个月末:1 对兔子。
  • 第 2 个月末:2 对兔子。
  • 从第 3 个月开始:总兔子数 = 上个月的总兔子数 + 上上个月的总兔子数。

动态规划的核心思想是将复杂问题分解为子问题,通过记录中间状态避免重复计算,降低时间复杂度。


问题分析与解法梳理

  1. 状态定义
    dp[i] 表示第 i 个月末兔子的总对数。

  2. 状态转移方程
    根据题目规律:

    dp[i]=dp[i−1]+dp[i−2]dp[i] = dp[i-1] + dp[i-2]dp[i]=dp[i−1]+dp[i−2]

    解释:

    • dp[i−1]dp[i-1]dp[i−1]:上个月的兔子总数(保留原有的成年兔子)。
    • dp[i−2]dp[i-2]dp[i−2]:上上个月的成年兔子,繁殖出的小兔子数。
  3. 初始条件

    • dp[1]=1dp[1] = 1dp[1]=1:第 1 个月末有 1 对兔子。
    • dp[2]=2dp[2] = 2dp[2]=2:第 2 个月末有 2 对兔子。
  4. 结果表达式
    返回 dp[A],即第 A 个月末兔子的总对数。


动态规划代码实现

以下是 Python 实现:

def rabbit_population(A):
    # 初始条件
    if A == 1:
        return 1
    if A == 2:
        return 2
    
    # 动态规划数组
    dp = [0] * (A + 1)
    dp[1], dp[2] = 1, 2
    
    # 状态转移
    for i in range(3, A + 1):
        dp[i] = dp[i - 1] + dp[i - 2]
    
    return dp[A]

# 测试用例
print(rabbit_population(1))  # 输出: 1
print(rabbit_population(5))  # 输出: 8
print(rabbit_population(15)) # 输出: 987

优化版本(滚动数组)

由于动态规划只依赖最近两个状态值,可以通过滚动数组优化空间复杂度,从 O(A)O(A)O(A) 降为 O(1)O(1)O(1):

def rabbit_population(A):
    if A == 1:
        return 1
    if A == 2:
        return 2
    
    prev, curr = 1, 2
    for _ in range(3, A + 1):
        prev, curr = curr, prev + curr
    
    return curr

# 测试用例
print(rabbit_population(1))  # 输出: 1
print(rabbit_population(5))  # 输出: 8
print(rabbit_population(15)) # 输出: 987

对入门同学的学习建议

  1. 理解问题本质
    这类问题的核心在于识别递推关系,结合动态规划的思想,通过保存中间结果避免重复计算。

  2. 明确动态规划四要素

    • 状态定义
    • 状态转移方程
    • 初始条件
    • 最终结果表达式
  3. 学习空间优化
    动态规划初学者往往直接创建数组存储所有状态,但对于类似斐波那契数列的问题,可以通过变量滚动降低空间复杂度。

  4. 举例验证递推
    在手动验证 dp[i]dp[i]dp[i] 的变化规律时,多画图、多代入几组小规模数据。


总结

这道题是动态规划的经典入门问题。通过对状态转移方程的推导,逐步掌握递推公式和优化技巧,可以为日后更复杂的动态规划问题打下扎实基础。