题目:给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小,每次只能向下或者向右移动一步
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。
先给出动态规划方程:dp[i][j] = min(dp[i-1][j],dp[i][j-1])+grid[i][j]
求左上到右下的最小路径和,看来又一个累加问题,可以从局部最小和到整体最小和。为了方便说明,我们对矩阵进行标号,左上角对于[0][0]位,右下角对应[2][2]位。到达[2][2]位可以从[1][2]或[2][1]到达,这就转化为从[0][0]到[1][2]和从[0][0]到[2][1]中取最小值。下面给出代码:
#include<iostream>
#include<vector>
using namespace std;
void printSum(vector<vector<long long>> sum)
{
for(int k=0;k<3;k++)
{
for(int z=0;z<3;z++)
{
cout << sum[k][z] << ",";
}
cout << endl;
}
}
int minPathSum(vector<vector<int>>& grid) {
int n=grid.size(); //这个vector里有几个vector元素
int m=grid[0].size(); //vector里面的vector大小
vector<vector<long long>> sum(n,vector<long long>(m,0));
int i,j;
sum[0][0] = grid[0][0];//左上角
for(i=1; i<n; i++)//纵向求和
{
sum[i][0] = sum[i-1][0]+grid[i][0];
}
for(j=1; j<m; j++)//横向求和
{
sum[0][j] = sum[0][j-1]+grid[0][j];
}
//n表示纵向,m表示横向
for(i=1; i<n; i++)
{
for(j=1; j<m; j++)
{
cout << "-------sum" << endl;
printSum(sum);
cout << "-----------------detail" << endl;
cout << "grid[i][j]=" << grid[i][j] << endl;
cout << "min=" << min(sum[i-1][j],sum[i][j-1]) << endl;
sum[i][j] = grid[i][j]+min(sum[i-1][j],sum[i][j-1]);
}
cout << "*******************************" << endl;
}
return sum[i-1][j-1];
}
int main(){
vector<vector<int>> v={{1,3,1},{1,5,1},{4,2,1}};
int n = minPathSum(v);
cout<< "n=" << n << endl;
}
运行结果:
-------sum
1,4,5,
2,0,0,
6,0,0,
-----------------detail
grid[i][j]=5
min=2
-------sum
1,4,5,
2,7,0,
6,0,0,
-----------------detail
grid[i][j]=1
min=5
*******************************
-------sum
1,4,5,
2,7,6,
6,0,0,
-----------------detail
grid[i][j]=2
min=6
-------sum
1,4,5,
2,7,6,
6,8,0,
-----------------detail
grid[i][j]=1
min=6
*******************************
n=7
sum用来存储从[0][0]到sum[i][j]路径的最小和,看看每次sum的变化,sum[1][1] = 7表明从[0][0]到[1][1]路径最小和是7,程序先把第2行对于的sum都求出来,再把第2列对应的sum都求出来,最后求sum[2][2]就很容易了。
参考地址:https://blog.csdn.net/weixin_43750513/article/details/106738099