第三章算法作业
1.1 最优子结构性质、递归方程式、定义与边界条件
(1)最优子结构性质
从左上角 (0,0) 到任意一个格子 (i,j) 的最小费用路径,一定是由到达其上方 (i-1,j) 或左方 (i,j-1) 的最小费用路径延伸而来。
因此,问题具有最优子结构:全局最优解包含子问题的最优解。
(2)递归方程式
设:
cost[i][j]:格子 (i,j) 的通过费用
dp[i][j]:从 (0,0) 到 (i,j) 的最小总费用
递归方程为:
dp[i][j] =
{
cost[0][0],i = 0,j = 0
dp[0][j-1] + cost[0][j],i = 0, j > 0
dp[i-1][0] + cost[i][0],i > 0, j = 0
cost[i][j] + min(dp[i-1][j], dp[i][j-1]),i>0, j>0
}
(3)定义说明
dp[i][j] 表示:
从起点 (0,0) 出发,只能向右或向下移动,到达格子 (i,j) 的最小总费用
每一步只能从上或左转移,符合题目“不能对角移动”的限制
(4)边界条件
起点:dp[0][0] = cost[0][0]
第一行(只能从左边来):dp[0][j] = dp[0][j-1] + cost[0][j]
第一列(只能从上边来):dp[i][0] = dp[i-1][0] + cost[i][0]
1.2 填表法中表的维度、填表范围、填表顺序及原问题最优值
(1)表的维度
使用二维表 dp[N][N]
维度:二维
每个元素 dp[i][j] 对应网格中的一个格子
(2)填表范围
行范围:i = 0, 1, 2, …, N-1
列范围:j = 0, 1, 2, …, N-1
覆盖整个 N × N 网格
(3)填表顺序
先填第 0 行
dp[0][0]
从左到右:dp[0][1], dp[0][2], …
再填第 0 列
从上到下:dp[1][0], dp[2][0], …
最后按行优先顺序填其余格子
外层循环 i = 1 → N-1
内层循环 j = 1 → N-1
该顺序保证:
计算 dp[i][j] 时,dp[i-1][j] 和 dp[i][j-1] 已经计算完成。
(4)原问题的最优值是哪个表格元素?
原问题:从左上角到右下角的最小费用
最优值存储在:dp[N-1][N-1],即右下角对应的表格元素。
1.3 时间和空间复杂度分析
(1)时间复杂度
需要计算每个格子一次,每个格子只做一次加法和一次 min 运算,总计算量:O(N^2)
(2)空间复杂度
使用了两个二维数组:cost[N][N],dp[N][N]
空间占用:O(N^2)
代码如下:
include
include
using namespace std;
int main() {
int N;
cin >> N;
int cost[100][100];
int dp[100][100];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cin >> cost[i][j];
}
}
dp[0][0] = cost[0][0];
for (int j = 1; j < N; j++) {
dp[0][j] = dp[0][j - 1] + cost[0][j];
}
for (int i = 1; i < N; i++) {
dp[i][0] = dp[i - 1][0] + cost[i][0];
}
for (int i = 1; i < N; i++) {
for (int j = 1; j < N; j++) {
dp[i][j] = cost[i][j] + min(dp[i - 1][j], dp[i][j - 1]);
}
}
cout << dp[N - 1][N - 1] << endl;
return 0;
}

浙公网安备 33010602011771号