算法第三章作业
“7-4 最低通行费”动态规划实践报告
一个商人穿过一个N×N的正方形的网格,去参加一个非常重要的商务活动。他要从网格的左上角进,右下角出。每穿越中间1个小方格,都要花费1个单位时间。商人必须在(2N-1)个单位时间穿越出去。而在经过中间的每个小方格时,都需要缴纳一定的费用。
这个商人期望在规定时间内用最少费用穿越出去。请问至少需要多少费用?
注意:不能对角穿越各个小方格(即,只能向上下左右四个方向移动且不能离开网格)。
1.1 递归方程、定义与边界条件
定义:
[dp[i][j]]
表示从左上角 ((1,1)) 走到格子 ((i,j)) 时,所需缴纳的最少通行费,且费用包含起点和当前格子的费用。
对于内部格子 ((i,j)),即 (i\geq2,\ j\geq2),到达该格子只可能来自:
- 上方格子 ((i-1,j));
- 左侧格子 ((i,j-1))。
因此递归方程为:
[dp[i][j]=\min(dp[i-1][j],dp[i][j-1])+a[i][j]]
边界条件如下:
[dp[1][1]=a[1][1]]
第一行只能从左向右到达:
[dp[1][j]=dp[1][j-1]+a[1][j],\quad 2\leq j\leq N]
第一列只能从上向下到达:
[dp[i][1]=dp[i-1][1]+a[i][1],\quad 2\leq i\leq N]
原问题的最优解为:
[dp[N][N]]
即从左上角到右下角所需的最少通行费。
1.2 填表法设计
动态规划表 dp 是一个二维数组,维度为:
[N \times N]
程序中采用下标从 1 开始的写法,因此定义为 dp[105][105],可满足题目 (N<100) 的要求。
填表范围及顺序如下:
- 先填左上角:
dp[1][1]; - 从左到右填第一行:
dp[1][2]至dp[1][N]; - 从上到下填第一列:
dp[2][1]至dp[N][1]; - 按行优先顺序填其余位置:外层循环 (i=2) 到 (N),内层循环 (j=2) 到 (N)。
这种顺序保证计算dp[i][j]时,所需的dp[i-1][j]和dp[i][j-1]都已经求出。
最终,表中右下角元素:
[dp[N][N]]
就是商人在规定时间内穿越网格的最少通行费。
1.3 时间复杂度和空间复杂度
共有 (N^2) 个状态,每个状态只进行一次取最小值和加法运算,均为常数时间,因此时间复杂度为:
[O(N^2)]
程序使用了费用数组 a 和动态规划数组 dp,二者均为二维数组,所占空间与网格规模成正比,因此空间复杂度为:
[O(N^2)]
若不要求保留完整的动态规划表,还可以使用一维数组滚动更新,将动态规划部分的空间降为 (O(N));但题目给出的代码采用二维表,故其实际空间复杂度为 (O(N^2))。
浙公网安备 33010602011771号