算法第三章作业

“最低通行费” 问题动态规划分析

1.1 递归方程式与边界条件
状态定义:设dp[i][j]表示从网格左上角(0,0)出发,到达第i行第j列位置时,累计的最小通行费用。
最优子结构与递归方程:
题目限定必须在2N-1个单位时间内穿越网格,而从左上角到右下角的最短路径(仅向右、向下移动)恰好需要经过2N-1个方格,因此商人无法走回头路,仅能通过向右或向下两个方向到达任意格子(i,j)。
因此,到达(i,j)的最小费用,等于“从上方格子(i-1,j)到达的最小费用” 和 “从左侧格子(i,j-1)到达的最小费用”中的较小值,再加上当前格子的费用a[i][j],递归方程式为:dp[i][j]=min(dp[i-1][j],dp[i][j-1])+a[i][j]
边界条件:

  1. 起点:dp[0][0]=a[0][0],起点的费用就是自身格子的费用。
  2. 第一行(i=0,j>0):只能从左侧格子向右移动到达,因此dp[0][j]=dp[0][j-1]+a[0][j]。
  3. 第一列(j=0,i>0):只能从上方格子向下移动到达,因此dp[i][0]=dp[i-1][0]+a[i][0]。
    1.2 填表法相关说明
    表的维度:使用二维数组dp,维度为N×N(与输入网格规模一致,下标范围为0≤i≤N-1,0≤j≤N-1)
    填表范围:覆盖整个N×N的二维表,所有格子的dp值均需计算填充。
    填表顺序:
  4. 先初始化起点dp[0][0]
  5. 从左到右填充第一行(i=0,j从1到N-1)
  6. 从上到下填充第一列(j=0,i从1到N-1)
  7. 剩余区域按行优先、从上到下、从左到右的顺序填充(i从1到N-1,每行内j从1到N-1)。该顺序保证计算dp[i][j]时,其依赖的dp[i-1][j](上方)和dp[i]j-1均已计算完成。
    最优值位置:原问题的最优值(全程最小通行费用)对应表格的右下角元素dp[N-1][N-1]。
    1.3 时间与空间复杂度分析
    时间复杂度:算法需要完整填充N×N的dp表格,每个格子的计算仅包含一次取最小值与一次加法,为O(1)操作,因此整体时间复杂度为O(N^2)。
    空间复杂度:使用了N×N的二维dp数组存储子问题结果,因此空间复杂度为O(N^2)。
    该问题可通过滚动数组优化,仅用一维数组保存上一行/当前行的结果,空间复杂度可降至O(N);题目给出的参考实现采用二维数组,空间复杂度为O(N²)。

对动态规划算法的理解和体会

动态规划是一种通过将复杂问题分解为重叠子问题、并存储子问题的解以避免重复计算的算法思想,核心依托于 “最优子结构” 与 “重叠子问题” 两大性质:问题的最优解可以由其子问题的最优解推导而来,且求解过程中会反复出现相同的子问题,通过记录子问题结果可以将指数级的暴力复杂度大幅降低。
结合 “最低通行费” 这道题可以很直观地体会动态规划的价值:如果用暴力枚举所有从起点到终点的路径,路径数量会随 N 呈指数级增长,当 N 接近 100 时完全无法计算;而通过定义dp[i][j]这个子问题状态,将“到终点的最小费用” 解为“到每个格子的最小费用”,每一步只依赖前一步的子问题结果,就把复杂度压缩到了平方级。

在我看来,动态规划最关键的步骤是状态定义和转移方程推导。状态定义决定了子问题的拆解方式,一旦状态定义不准确,后续的转移关系就会出错;而转移方程则是抓住最优子结构的核心,需要先理清问题的约束和可达路径 ,比如这道题中“2N-1时间”的约束看似是限制,实际上是在暗示只能向右、向下移动,直接确定了每个格子只能由上方和左方转移而来,是推导转移方程的关键。
除此之外,边界条件的处理也十分重要,它是递推的起点,第一行、第一列的特殊情况如果处理疏漏,会导致整个表格的计算全部出错。整体而言,动态规划是一种 “以空间换时间” 的策略,它不需要复杂的递归调用,通过自底向上的填表就能高效求解,是解决路径规划、序列匹配、背包等最优化问题的强力工具,也让我体会到:算法优化的核心,往往是找到问题中重复计算的部分,并用合适的方式将其复用。

posted @ 2026-11-03 22:57  小米粥米小  阅读(8)  评论(0)    收藏  举报