算法第三章作业

  1. 实践报告
    1.1 根据最优子结构性质列出递归方程式
    1.1.1 状态定义
    设 a[i][j] 表示第 i 行第 j 列方格本身的费用;dp[i][j] 表示从左上角 (1,1) 出发、只允许向右或向下移动,到达方格 (i,j) 时的最小累计通行费(含终点方格自身的费用)。
    由于必须在恰好 2N-1 个单位时间内穿越(即 N-1 次向右、N-1 次向下),任何向上或向左的移动都会使总步数超过 2N-1,因此最优路径中只可能包含向右和向下两种移动。

1.1.2 递归方程式
dp[i][j] = a[i][j] + min(dp[i-1][j], dp[i][j-1]) (i>1 且 j>1)
dp[i][1] = a[i][1] + dp[i-1][1] (第一列,i>1)
dp[1][j] = a[1][j] + dp[1][j-1] (第一行,j>1)

1.1.3 边界条件
dp[1][1] = a[1][1] (左上角为起点)
最优子结构说明:到达 (i,j) 的最优路径,其最后一步必然来自上方 (i-1,j) 或左方(i,j-1)。若某一段不是到达其前驱格子的最优路径,则可用更优的路径替换,得到更小的 dp[i][j],与原假设矛盾。因此问题满足最优子结构性质,可采用动态规划求解。

1.2 填表法的维度、填表范围和填表顺序
·表的维度:使用一个与网格同规模的 N×N 二维数组 dp 作为状态表。
·填表范围:i∈[1,N],j∈[1,N],即表内所有元素都需要计算。
·填表顺序:采用行优先顺序(按行从上到下,每行内部从左到右)填表;因为dp[i][j] 只依赖 dp[i-1][j](上一行)与 dp[i][j-1](本行左侧),按该顺序填表时两个依赖项均已算好;也可按对角线顺序填表。
·原问题最优值:原问题的最优值对应状态表右下角元素 dp[N][N],即从左上角到右下角的最小总通行费。

1.3 时间与空间复杂度分析
·时间复杂度:状态表共有 N×N 个元素,每个元素的计算只进行常数次运算(一次加法和一次取最小值比较),因此时间复杂度为 O(N²)。
·空间复杂度:需要存储完整的 N×N 二维状态表,因此空间复杂度为 O(N²)。
·空间优化:由于 dp[i][j] 只依赖上一行与当前行左侧的元素,可以采用滚动数组只保留两行(甚至一维数组从右向左更新),将空间复杂度降至 O(N),时间复杂度保持不变。

  1. 你对动态规划算法的理解和体会
    动态规划的核心思想是利用最优子结构、重叠子问题与无后效性,把一个大问题拆解成规模更小的子问题,并保存子问题的答案以避免重复计算,从而用多项式时间解决原本需要指数级枚举的问题。
    通过本题的分析,我体会到:第一,最优子结构是使用动态规划的前提,只有“大问题的最优解包含子问题最优解”时,递推关系才成立;本题中到达任意格子的最小费用,一定建立在到达其上方或左方格子的最小费用之上。第二,重叠子问题是动态规划相对暴力搜索的优势所在,不同路径会反复访问同一个格子,填表法把每次结果记录下来,只计算一次。第三,无后效性保证了递推的可行:一旦算出到达 (i,j) 的最小费用,后续决策只依赖这个数值,而不关心具体是怎么走过来的,因此可以按确定顺序自底向上填表。
    动态规划的解题流程通常是:分析最优子结构 → 定义状态并写出递推方程 → 确定边界条件 → 设计填表顺序 → 填表求解。这一套方法不仅适用于网格路径问题,也广泛适用于背包、最长公共子序列、区间合并、树形与状态机等问题。掌握好状态设计和递推方程的推导,是写出高效动态规划程序的关键。
posted @ 2026-11-03 22:25  赐予秋  阅读(2)  评论(0)    收藏  举报