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

如何用Top Down法求解钢条切割问题:返回全长度最大收益及切割方案

带记忆化的Top-Down钢条切割解法(含收益列表与切割方案)

嘿,既然你已经搞定了自底向上的钢条切割,那理解Top-Down的思路就很顺了——核心就是递归+备忘录(记忆化),避免重复计算子问题,同时我们可以同步记录每个长度的最优切割点,最后导出完整的切割方案。

整体思路

Top-Down动态规划的逻辑是:

  • 从目标长度开始,递归分解成更小的子问题;
  • 用备忘录数组存储已经计算过的子问题结果,避免重复计算;
  • 同时维护一个切割点数组,记录每个长度对应的最优第一次切割长度,方便后续生成切割方案。

完整代码实现

def cut_rod_top_down(pricelist):
    n = len(pricelist) - 1  # 目标钢条长度(pricelist[0]对应长度0的收益)
    # 初始化备忘录:r[i]存储长度i的最大收益,s[i]存储长度i的最优第一次切割长度
    r = [-1] * (n + 1)
    s = [0] * (n + 1)
    r[0] = 0  # 长度0收益为0

    def memoized_cut_rod(length):
        if r[length] != -1:
            # 已经计算过,直接返回备忘录的值
            return r[length]
        max_val = 0
        best_cut = 0
        # 遍历所有可能的切割点:从1到当前length
        for i in range(1, length + 1):
            current_val = pricelist[i] + memoized_cut_rod(length - i)
            if current_val > max_val:
                max_val = current_val
                best_cut = i  # 记录最优切割点
        r[length] = max_val
        s[length] = best_cut
        return max_val

    # 计算从0到n所有长度的最大收益
    for length in range(n + 1):
        memoized_cut_rod(length)
    
    # 生成每个长度的切割方案
    def get_cut_scheme(length):
        scheme = []
        while length > 0:
            cut = s[length]
            scheme.append(cut)
            length -= cut
        return scheme
    
    # 生成0到n所有长度的切割方案列表
    schemes = [get_cut_scheme(i) for i in range(n + 1)]
    
    return r, schemes

代码解释

  1. 备忘录初始化:

    • r数组:初始化为-1(表示未计算),r[0]设为0(长度0的钢条收益为0);
    • s数组:存储每个长度的最优第一次切割长度,初始为0。
  2. 递归记忆化函数:

    • 如果当前长度的收益已经计算过(r[length] != -1),直接返回;
    • 遍历所有可能的切割点i,计算切割成i和length-i两段的总收益,更新最大收益和对应的切割点;
    • 将计算结果存入备忘录,记录切割点。
  3. 生成切割方案:

    • get_cut_scheme函数通过回溯s数组,从目标长度开始,每次取最优切割点,直到剩余长度为0,得到完整的切割分段方案;
    • 最后生成从长度0到目标长度的所有方案列表。

测试示例

假设我们的价格列表是pricelist = [0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30](对应长度0到10的价格),调用函数:

pricelist = [0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30]
max_revenues, cut_schemes = cut_rod_top_down(pricelist)

# 打印长度0到10的最大收益
print("各长度最大收益:", max_revenues)
# 打印各长度的切割方案
for i in range(len(max_revenues)):
    print(f"长度{i}的最优切割方案:{cut_schemes[i]}")

输出结果会和自底向上的解法完全一致,但实现方式是自上而下的递归+记忆化。

和自底向上的对比

  • Top-Down更符合直观的递归思路,不需要按顺序计算子问题,备忘录会自动处理依赖;
  • 两种方法的时间复杂度都是O(n²),空间复杂度都是O(n),效率相近。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:31:11