第三章算法作业
第三章算法作业
1.1 最优子结构与递归方程式
问题分析:
商人从网格左上角进入,右下角离开,且必须在 2N- 个单位时间内穿越出去。由于每经过一个格子消耗 1 个单位时间,从左上角到右下角至少需要经过 2N-1 个格子,因此商人只能向右或向下移动,不能回头。
状态定义:
设 dp[i][j] 表示从左上角 (0,0) 走到格子 (i,j) 所需的最小费用。
递归方程式:
if (i == 0 && j == 0)
dp[i][j] = p[i][j];
else if (i == 0)
dp[i][j] = dp[i][j-1] + p[i][j];
else if (j == 0)
dp[i][j] = dp[i-1][j] + p[i][j];
else
dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + p[i][j];
边界条件:
- 起点:
dp[0][0] = p[0][0]。 - 第一行:只能从左边格子过来,因此
dp[0][j] = dp[0][j-1] + p[0][j]。 - 第一列:只能从上边格子过来,因此
dp[i][0] = dp[i-1][0] + p[i][0]。
最优子结构:
到达 (i,j) 的最小费用路径中,到达 (i-1,j) 或 (i,j-1) 的子路径也必须是最小费用路径。否则,可以用更优的子路径替换,从而得到更优的整体解,这与最优解矛盾。因此该问题具有最优子结构性质。
1.2 填表法分析
| 项目 | 说明 |
|---|---|
| 表的维度 | 二维表 dp[N][N] |
| 填表范围 | i ∈ [0, N-1],j ∈ [0, N-1] |
| 填表顺序 | 按行从上到下、每行从左到右依次填表 |
| 依赖关系 | 计算 dp[i][j] 时需要 dp[i-1][j] 和 dp[i][j-1],按上述顺序可保证子问题已求解 |
| 原问题最优值 | dp[N-1][N-1],即从左上角到右下角的最小费用 |
1.3 时间与空间复杂度分析
时间复杂度:
程序使用两层循环遍历整 网格,每个格子只计算一次,每次计算只进行常数次比较和加法操作,因此时间复杂度为:O(N^2)
空间复杂度:
程序使用了两个二维数组 p[MAXN][MAXN] 和 dp[MAXN][MAXN],每个数组大小为,因此空间复杂度为:O(N^2)
如果进一步优化,可以只保留一行或一列的 DP 值,将空间复杂度降低到 O(N)。
对动态规划算法的理解和体会
通过这次实验,我对动态规划算法有了更具体的认识。动态规划并不是简单地“套公式”,而是要先分析问题的最优子结构,再设计合适的状态表示,最后根据状态之间的依赖关系写出递推式。
在这道“最低通行费”题目中,最关键的一步是确定状态 dp[i][j] 表示从起点走到 (i,j) 的最小费用。状态确定后,转移方程就比较自然:商人只能从上方或左方进入当前格子,因此取两者中的较小值,再加上当前格子的费用即可。
同时,边界条件也非常重要。第一行和第一列没有两个方向可以转移,必须单独处理。填表顺序也需要保证子问题先被计算,否则会出现使用未初始化值的情况。
与暴力搜索相比,动态规划通过保存子问题的解,避免了重复计算,显著提高了效率。这种“以空间换时间”的思想让我认识到,算法设计不仅要考虑结果是否正确,还要考虑如何减少不必要的计算。动态规划对问题建模能力要求较高,但只要状态定义清晰,递推关系往往就能比较自然地得到。
代码实现如下:
#include <iostream>
#include algorithm>
using namespace std;
const int MAXN = 105;
int p[MAXN][MAXN];
int dp[MAXN][MAXN];
int main() {
int N;
cin >> N;
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
cin >> p[i][j];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (i == 0 && j == 0) {
dp[i][j] = p[i][j]; // 起点
} else if (i == 0) {
dp[i][j] = dp[i][j-1] + p[i][j]; // 第一行,只能从左边来
} else if (j == 0) {
dp[i][j] = dp[i-1][j] + p[i][j]; // 第一列,只能从上边来
} else {
dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + p[i][j];
}
}
}
cout << dp[N-1][N-1] << endl;
return 0;
}

浙公网安备 33010602011771号