【题目描述】
给定一个 n * m 的矩阵 a,从左上角开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的数字累加起来就是路径和,输出所有的路径中最小的路径和。
输入描述
第一行输入两个整数 n 和 m,表示矩阵的大小。
接下来 n 行每行 m 个整数表示矩阵。
输出描述
输出一个整数表示答案。
示例1
输入
4 4
1 3 5 9
8 1 3 4
5 0 6 1
8 8 4 0
输出
12
备注
1≤n,m≤2000
0≤aij ≤100
【代码实现 - CPP版】
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
/*
* 动态规划
* 1. 确定可变参数:矩阵的两个维度 -- 一旦确定,其返回值即代表一个特定的最终状态
* 2. 利用可变参数构建row * col二维数组dp[][]
* 其中row取值范围:0, ..., n
* col取值范围:0, ..., m
* 3. 确定最终状态:dp[n-1][m-1]
* 4. 确定base case初始化二表: 矩阵的首行首列也即dp[0][...], dp[...][0]
* 5. 找出其他位置的递推公式: dp[i][j] = min{dp[i][j-1], dp[i-1][j]} + vec_arr[i][j]
* 6. 依据上述递推公式一次从第二行由左至右计算每个位置的值,返回右下角的值dp[n-1][m-1]
*/
int minPaths(const vector<vector<int>> vec_arr) {
int row = vec_arr.size();
int col = vec_arr[0].size();
// ignore input params judgement
vector<vector<int>> vec_dp(row, vector<int>(col, 0));
// init base case
vec_dp[0][0] = vec_arr[0][0];
// the first row
for (int i=1; i<col; i++) {
vec_dp[0][i] = vec_dp[0][i-1] + vec_arr[0][i];
}
// the first column
for (int j=1; j<row; j++) {
vec_dp[j][0] = vec_dp[j-1][0] + vec_arr[j][0];
}
// other scerios
for (int i=1; i<row; i++) {
for (int j=1; j<col; j++) {
vec_dp[i][j] = min(vec_dp[i][j-1], vec_dp[i-1][j]) + vec_arr[i][j];
}
}
return vec_dp[row-1][col-1];
}
int main() {
int m, n;
cin >> n >> m;
if ((1 > m || 2000 < m) || (1 > n || 2000 < n)) {
cout << "Invalid input parameter(s)!" <<endl;
}
vector<vector<int>> vec(n, vector<int>(m, 0));
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
int tmp;
cin>>tmp;
vec[i][j] = tmp;
}
}
cout << minPaths(vec) <<endl;
return 0;
}