第三章作业

1.1 递归方程式及边界条件
设 dp[i][j] 表示从网格左上角 (1, 1) 走到第 i 行第 j 列的小方格时,所需要的最少费用。
题目要求必须在 (2N-1) 个单位时间内穿越出去,且只能上下左右移动。在一个 N*N 的网格中,从左上角到右下角最短路径正好需要 (N-1) + (N-1) + 1 = 2N-1 步。这意味着商人不能走回头路,只能向右或向下移动。因此,到达格子 (i, j) 只能从上方 (i-1, j) 或左侧 (i, j-1) 过来。要使得总费用最少,只需选择这两种方式中到达该格子前费用较小的一个,再加上当前格子的费用即可。

递归方程式:
dp[i][j] = cost[i][j] + min(dp[i-1][j], dp[i][j-1])
(其中 cost[i][j] 为网格中第 i 行第 j 列的费用)

边界条件:
起点: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)

1.2 填表法(DP表)
表的维度:二维数组,大小为 N*N(代码中常建 N+1 大小以方便使用 1-based 索引)。
填表范围:外层循环 i 从 1 遍历到 N,内层循环 j 从 1 遍历到 N。
填表顺序:从上到下,从左到右。因为计算 dp[i][j] 需要依赖上方元素 dp[i-1][j] 和左侧元素 dp[i][j-1],所以必须先计算完这些元素。
原问题的最优值:填表完成后,最终要求的原问题最优解存放在表格的右下角,即 dp[N][N]。

1.3 算法复杂度分析
时间复杂度:O(N^2)。算法使用了两层嵌套的 for 循环遍历整个 NN 的网格,每个格子的状态转移只需 O(1) 的时间。
空间复杂度:O(N^2)。代码中使用了 cost 矩阵和 dp 矩阵,大小均为 NN。如果需要优化,因为 dp[i][j] 只依赖于当前行和上一行,可以通过滚动数组将空间复杂度优化至 O(N)。

对动态规划算法的理解和体会
动态规划的核心是以空间换时间。暴力搜索会产生大量的重复计算,通过引入 dp 数组将计算过的子问题结果记录下来,再次需要时直接查表,能将指数级的时间复杂度降到多项式级。
把握最优子结构和无后效性。大问题的最优解由小问题的最优解推导得出;当前状态一旦确定,就不受未来状态的影响。本题中,无论商人以前怎么走到 (i, j),只要当前到达了这里,之前走过的路径对后续向右向下的选择都不产生影响。
细节决定成败。编写代码时,第一行和第一列的越界问题是常见陷阱。通过扩充数组大小、初始化极大值,并在代码中特判起点,可以安全地避免繁琐的边界判断。

posted @ 2026-11-01 15:52  elecsea  阅读(8)  评论(0)    收藏  举报