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

Python动态规划实现疑问:算法4.8中s的取值与f(s)最小化实现

解决动态规划Algorithm 4.8中的最优分割点问题及Python实现

我来帮你理清这个动态规划的逻辑并修正代码问题~你提到的困惑其实是动态规划中「枚举所有可能子问题,选择最优解」的核心步骤,咱们一步步拆解:

先解答你的核心疑惑

为何书中既在for循环中使用s,又要将s设为使f(s)最小的取值?

这里的for循环是枚举所有可能的分割点:当我们要把前t+1个元素(因为x是0索引)分成j+1个区间时,s代表前j个区间的最后一个元素的索引,剩下的s+1到t就是第j+1个区间。

而f(s) = max(r[s][j-1], (x[t]-x[s+1])/2)的含义是:这个分割方案下的「最大代价」(前j个区间的最优最大代价,加上当前区间的代价,取两者的最大值)。我们的目标是找到所有可能分割点中,这个最大代价最小的那个——这正是动态规划「最优子结构」的体现:全局最优解由子问题的最优解组合而来。

你当前的代码问题在于:每次遍历s时直接覆盖r[t][j],最后得到的是最后一个s对应的f(s),而不是所有可能中的最小值,这就偏离了算法的要求。

修正后的Python实现

我调整了代码的核心逻辑,同时修正了几个细节错误,注释里写清楚了每一步的作用:

x = [1,2,5,6,10]
k = 3  # 要划分的区间数量
n = len(x)  # 用len(x)代替硬编码的5,更灵活
# 初始化r和c矩阵:r记录最优最大代价,c记录各区间的中心点
r = [[0 for _ in range(k)] for _ in range(n)]
c = [[[] for _ in range(k)] for _ in range(n)]

def Union(lst1, lst2):
    return lst1 + lst2

for j in range(k):
    for t in range(n):
        if j == 0:
            # j=0时只有1个区间,覆盖x[0]到x[t]
            r[t][j] = (x[t] - x[0]) / 2
            c[t][j] = [(x[t] + x[0]) / 2]
        else:
            # 初始化最小代价为无穷大,用来后续比较
            min_max_cost = float('inf')
            best_split_s = -1  # 记录最优分割点s
            
            # 遍历所有可能的分割点s:从0到t-1(s是前j-1个区间的最后一个元素索引)
            for s in range(t):
                # 计算当前分割点对应的最大代价
                current_cost = max(r[s][j-1], (x[t] - x[s+1]) / 2)
                # 如果当前代价更小,更新最小值和最优分割点
                if current_cost < min_max_cost:
                    min_max_cost = current_cost
                    best_split_s = s
            
            # 用最优分割点的结果更新r和c
            r[t][j] = min_max_cost
            # 当前区间的中心点是(x[t]+x[s+1])/2,合并前j-1个区间的中心点
            current_center = (x[t] + x[best_split_s + 1]) / 2
            c[t][j] = Union(c[best_split_s][j-1], [current_center])

# 打印结果
print("最优最大代价矩阵r:")
for row in r:
    print([round(val, 2) for val in row])  # 保留两位小数更易读
print("\n各区间中心点矩阵c:")
for row in c:
    print([round(val, 2) for val in row])

关键修改说明

  1. 初始化逻辑优化:把c的初始值改为空列表,避免原代码中c[s][j-1] == 0的错误判断(因为c存储的是中心点列表,不是数值0)。
  2. 最优分割点的寻找:先初始化最小代价为无穷大,遍历所有s计算代价,只保留最小的那个代价和对应的s,最后再用这个最优s更新r和c。
  3. 遍历范围修正:原代码中range(t-1)会漏掉s=0的情况,改为range(t)才能覆盖所有可能的分割点。

运行这段代码后,你就能得到Algorithm4.8要求的最优结果啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:24:53