题解 | #矩阵的最小路径和#
矩阵的最小路径和
https://www.nowcoder.com/practice/2fb62a4500af4f4ba5686c891eaad4a9
由于每次只能向右或者向下,所以可以使用如下方法:
方法一:
使用和原矩阵同等大小的dp矩阵,用以记录左上角点到当前点的最小路径和。
每一点只可能来自左或上这两个位置
#include<bits/stdc++.h>
using namespace std;
int minTraceSum(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[0].empty())
return 0;
int n = matrix.size();
int m = matrix[0].size();
//代表左上角到当前点的最短路径和
vector<vector<int>> dp(n, vector<int>(m));
//左上角
dp[0][0] = matrix[0][0];
//左上角起的竖直行
for (int i = 1; i < n; i++) {
dp[i][0] = matrix[i][0] + dp[i - 1][0];
}
//左上角起的水平行
for (int i = 1; i < m; i++) {
dp[0][i] = matrix[0][i] + dp[0][i - 1];
}
//其余部分
for (int i = 1; i < n; i++) {
for (int j = 1; j < m; j++) {
int minV=min(dp[i-1][j],dp[i][j-1]);
dp[i][j]=minV+matrix[i][j];
}
}
return dp[n-1][m-1];
}
int main() {
int n, m;
cin >> n >> m;
vector<vector<int>> matrix(n, vector<int>(m));
for (auto i = 0; i < n; i++) {
for (auto j = 0; j < m; j++) {
cin >> matrix[i][j];
}
}
auto res=minTraceSum(matrix);
cout<<res<<endl;
return 0;
}
方法二:
压缩矩阵
#include<bits/stdc++.h>
using namespace std;
int minTraceSum(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[0].empty())
return 0;
int n = matrix.size();
int m = matrix[0].size();
//代表左上角到当前点的最短路径和
//dp仅一层,起始时为[0][0]点到[0][j]点的最短路径和,
//终止时为[0][0]点到[n-1][j]点的最短路径和
//即不断滚动更新
vector<int> dp(m);
//起始时,第一行
dp[0] = matrix[0][0];
for (int j = 1; j < m; j++) {
dp[j] = dp[j - 1] + matrix[0][j];
}
//后面的行
for (int i = 1; i < n; i++) {
for (int j = 0; j < m; j++) {
//每行起始第一个,即[i][0]
if (j == 0) {
//未更新前的dp[j]代表上一行j位置的最短路径和
dp[j] += matrix[i][j];
} else {
//dp[j-1]代表左侧位置,即[0][0]到[i-1][j]处的最短路径和
//此处的dp[j]还未更新,代表[0][0]到[i][j-1]处的最短路径和
//取最小值为了判断是从左边还是从上边来时路径和更小
dp[j] = min(dp[j-1],dp[j])+matrix[i][j];
}
}
}
return dp[m-1];
}
int main() {
int n, m;
cin >> n >> m;
vector<vector<int>> matrix(n, vector<int>(m));
for (auto i = 0; i < n; i++) {
for (auto j = 0; j < m; j++) {
cin >> matrix[i][j];
}
}
auto res = minTraceSum(matrix);
cout << res << endl;
return 0;
}
查看16道真题和解析