第三章作业
一、问题分析
商人从 N×N 网格左上角 (1,1) 进入,右下角 (N,N) 离开,只能上下左右移动,每穿越一个小方格花费 1 单位时间,必须在 (2N-1) 个单位时间内穿越出去。
关键洞察:从 (1,1) 到 (N,N) 若只走最短路径(只向右或向下),恰好经过 2N-1 个方格,正好用满 2N-1 个单位时间。任何绕路(向上或向左)都会超时。因此问题等价于:只能向右或向下移动,求从左上角到右下角的最小费用路径。
1.1 递归方程式(最优子结构)
状态定义:设 dp[i][j] 表示从起点 (1,1) 到达方格 (i,j) 所需的最小费用(含 (i,j) 本身的费用)。
最优子结构分析:到达 (i,j) 的最后一步只能来自上方 (i-1,j) 或左方 (i,j-1)。要使到达 (i,j) 的总费用最小,其前驱格子的路径费用也必须最小——这正是最优子结构性质。
递归方程式:
text
dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + cost[i][j] (i>1 且 j>1)
边界条件:
text
dp[1][1] = cost[1][1] (起点费用)
dp[1][j] = dp[1][j-1] + cost[1][j] (j>1,第一行只能从左来)
dp[i][1] = dp[i-1][1] + cost[i][1] (i>1,第一列只能从上来)
其中 cost[i][j] 为方格 (i,j) 的费用;时间约束迫使路径只能向右/向下,故转移只考虑上方和左方。
1.2 填表法
表的维度:二维表 dp[N+1][N+1](下标从 1 开始,与网格坐标对应)。表中元素 dp[i][j] 表示到达 (i,j) 的最小费用。
填表范围:i = 1..N,j = 1..N,覆盖整个网格。
填表顺序:按行从上到下(i 递增)、每行从左到右(j 递增)。因为计算 dp[i][j] 依赖 dp[i-1][j](上一行,已算)和 dp[i][j-1](本行左边,已算),此顺序保证依赖项先于当前项计算完成。
原问题最优值:dp[N][N],即表格右下角元素。
1.3 复杂度分析
时间复杂度:填表共 N×N 个元素,每个元素计算(取 min 加一个数)为 O(1),故总时间为 O(N²)。N<100 时约 10⁴ 次运算,完全可行。
空间复杂度:二维表需 O(N²) 空间。可优化:由于 dp[i][j] 只依赖上一行和本行左侧,可用一维滚动数组 dp[j],按 dp[j] = min(dp[j], dp[j-1]) + cost[i][j] 更新,空间降为 O(N)。主算法采用 O(N²),优化版为 O(N)。
二、对动态规划算法的理解和体会
通过本题的实践,我对动态规划有了更深入的认识:
识别问题的“隐藏约束”是关键。题目表面允许四方向移动,但 (2N-1) 的时间约束实际上把可行路径限制为只向右/向下。DP 建模前必须先剖析问题本质结构,约束条件往往能大幅简化状态空间。
最优子结构是 DP 的基石。本题中“到达 (i,j) 的最优路径,其前缀路径对前驱格子也必最优”这一性质,使大问题可分解为子问题。若子问题最优不能推出全局最优,就不能直接 DP。
状态定义决定方程式的形式。dp[i][j] 定义为“到达该格的最小费用”而非其他,使转移自然、边界清晰。好的状态定义应满足:无后效性、可递推、能覆盖所有子问题。
填表顺序体现依赖关系。二维表格按行优先填充,本质是拓扑排序——保证依赖项先算。理解“依赖 → 顺序”的对应关系,比死记“从左到右、从上到下”更重要。
DP 与贪心的区别。本题若贪心地每步选费用小的方向,会陷入局部最优。DP 通过枚举所有前驱并取 min,保证全局最优,这正是 DP“记录所有子问题解、避免重复计算”的价值所在。
空间优化是锦上添花。滚动数组将 O(N²) 降为 O(N),体现 DP 中“当前状态只依赖有限前驱”的特性。
总之,动态规划的核心流程可概括为:分析最优子结构 → 定义状态 → 写递归方程与边界 → 确定填表顺序 → 求原问题解 → 分析并优化复杂度。本题虽小,却完整走通了这一流程,加深了我对“用表格记录子问题、用递推构造最优解”这一思想的掌握。

浙公网安备 33010602011771号