You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python二维递归动态规划实现陷入无限循环问题排查

动态卡牌游戏递归解法的性能问题分析

问题背景

来自《量化金融面试实用指南》编号5.3的动态卡牌游戏,其递推公式为:
E[f(b,r)] = max(b−r,(b/(b+r))∗E[f(b−1,r)]+(r/(b+r))∗E[f(b,r−1)])
边界条件:
f(0,r)=0, f(b,0)=b

你实现的递归代码如下:

def f(b,r):
    if b == 0:
        return 0
    elif r == 0:
        return b
    else:
        var = (b/(b+r)) * f(b-1, r) + (r/(b+r)) * f(b, r-1) 
        return max( b-r,  var )

print("The solution is")
print(f(26,26))

该代码在处理f(5,5)这类小输入时正常返回结果,但处理f(26,26)时迟迟无法返回,并非无限循环,而是重复计算导致的指数级时间复杂度。

问题原因

递归过程中,大量(b,r)组合会被反复计算:比如计算f(26,26)时会调用f(25,26)和f(26,25),而这两个子问题又都会调用f(25,25),f(25,25)又会触发更多重复的子问题。随着b和r数值增大,总计算量呈爆炸式增长,看似“卡住”实际是在做大量重复运算,耗时极长。

优化方案

方案1:记忆化缓存(Memoization)

用缓存存储已经计算过的(b,r)结果,避免重复计算,可通过Python内置的lru_cache装饰器快速实现:

from functools import lru_cache

@lru_cache(maxsize=None)
def f(b, r):
    if b == 0:
        return 0.0
    elif r == 0:
        return float(b)
    else:
        var = (b/(b+r)) * f(b-1, r) + (r/(b+r)) * f(b, r-1)
        return max(b - r, var)

print("The solution is")
print(f(26,26))

lru_cache会自动缓存函数的输入参数与对应返回值,每个(b,r)组合仅计算一次,时间复杂度降至O(b*r),能快速处理大输入。

方案2:迭代式动态规划(自底向上)

从边界条件出发,按顺序计算所有小的(b,r)组合,逐步推导到目标值:

def f(b, r):
    # 创建二维数组存储中间结果
    dp = [[0.0]*(r+1) for _ in range(b+1)]
    # 初始化边界条件
    for i in range(b+1):
        dp[i][0] = float(i)
    for j in range(r+1):
        dp[0][j] = 0.0
    # 填充动态规划表
    for i in range(1, b+1):
        for j in range(1, r+1):
            var = (i/(i+j)) * dp[i-1][j] + (j/(i+j)) * dp[i][j-1]
            dp[i][j] = max(i - j, var)
    return dp[b][r]

print("The solution is")
print(f(26,26))

自底向上的方式直接按依赖顺序计算所有子问题,同样避免重复计算,空间复杂度为O(b*r),处理大输入效率同样很高。

内容的提问来源于stack exchange,提问作者nyan314sn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 01:25:27