算法第三章作业 —— 最低通行费
算法第三章作业 —— 最低通行费
题目描述
一个商人要穿过 N×N 的网格,从左上角到右下角,每个格子有费用,找一条费用最少的路。商人必须在 2N-1 时间内到达,所以实际上只能向右和向下走,不能绕路。
输入格式:
- 第一行 N(1 ≤ N < 100)
- 接下来 N 行,每行 N 个整数,表示每个格子的费用
输出:最少费用
样例输入:
5
1 4 6 8 10
2 5 7 15 17
6 8 9 18 20
10 11 12 19 21
20 23 25 29 33
样例输出:
109
1. 实践报告
1.1 最优子结构、递归方程式与边界条件
最优子结构
设 dp[i][j] 表示从起点 (0,0) 走到格子 (i,j) 的最小费用。要求走到 (i,j) 的最优解,最后一步要么从上方 (i-1,j) 向下走,要么从左方 (i,j-1) 向右走,取两者中费用较小的那个,再加上当前格子的费用 cost[i][j]。
递归方程式
dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + cost[i][j]
其中 dp[i][j] 定义为从 (0,0) 走到 (i,j) 的最小费用,cost[i][j] 为格子 (i,j) 的费用。
边界条件
- dp[0][0] = cost[0][0],起点的费用
- dp[i][0] = dp[i-1][0] + cost[i][0],第一列只能从上方一路向下
- dp[0][j] = dp[0][j-1] + cost[0][j],第一行只能从左方一路向右
1.2 填表说明
表的维度
二维数组 dp,大小为 N × N。
填表范围
i 和 j 均从 0 到 N-1。
填表顺序
先填 dp[0][0],再填第一行(j 从 1 到 N-1)和第一列(i 从 1 到 N-1),然后按行优先顺序双层循环填完 i=1N-1、j=1N-1 的所有格子。
最优值位置
原问题的最优值是 dp[N-1][N-1],即右下角那个格子。
1.3 时间复杂度和空间复杂度
时间复杂度
需要填写 N×N 个格子,每个格子的计算只需常数次比较和加法操作,因此时间复杂度为 O(N²)。
空间复杂度
dp 数组大小为 N×N,空间复杂度为 O(N²)。
2. 对动态规划算法的理解和体会
分治和动态规划的区别是分治的子问题独立,动态规划的子问题有重叠。动态规划要满足最优子结构,就是原问题的最优解包含子问题的最优解。
写动态规划的时候,最关键的是想清楚 dp 数组到底代表什么。一旦定义清楚了,递归方程就好写了。然后注意边界条件和填表顺序,确保算 dp[i][j] 的时候它依赖的值已经算好了。
动态规划比贪心慢一点,但贪心有的时候不对,动态规划能保证对。
这次做最低通行费这题,一开始没注意时间限制 2N-1,以为可以四面八方走,后来发现实际上只能向右和向下,就变成了一个很基础的二维 dp 问题。说明审题很重要。
浙公网安备 33010602011771号