路径类 DP 是线性 DP 的一种,通常在一个 n × m 的矩阵中设定行走规则,研究从起点到终点的方案数、最小路径和或最大路径和等问题。入门阶段的《数字三角形》其实也属于这一范畴。
矩阵的最小路径和
题目解析
状态定义 dp[i][j] 表示从 (1, 1) 格子走到 (i, j) 格子时,所有方案下的最小路径和。
状态转移方程 我们根据最后一步来推导。要到达最后一个格子 dp[n][m],只能从上方 dp[n - 1][m] 或者左方 dp[n][m - 1] 走过来。因此,dp[n][m] 的值就是这两个位置较小值加上当前格子的权值 a[n][m]。公式如下: dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + a[i][j]
初始化 填表时需要访问左边和上边的格子,所以边界情况需要特殊处理。第一行和第一列在计算时会访问到第 0 行和第 0 列,但这两行无意义,所以我们将第 0 行和第 0 列初始化为无穷大。由于状态转移取最小值,这样永远不会选到无效区域。 此外,需要将 dp[1][1] 初始化为 a[1][1],因为起点的代价就是它本身。注意在填表循环中跳过 (1, 1) 格子,避免重复计算导致错误。
填表顺序 从上往下,从左往右。
输出结果 dp[n][m]
#include <iostream>
#include <cstring>
using namespace std;
const int N = 510;
int n, m;
int a[N][N], dp[N][N];
int main() {
// 处理输入
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> a[i][j];
}
}
// 初始化
memset(dp, 0x3f3f3f3f, sizeof(dp));
dp[1][1] = a[][];
( i = ; i <= n; i++) {
( j = ; j <= m; j++) {
(i == && j == ) ;
dp[i][j] = (dp[i - ][j], dp[i][j - ]) + a[i][j];
}
}
cout << dp[n][m] << endl;
;
}


