给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例:
输入: [ [1,3,1], [1,5,1], [4,2,1] ] 输出: 7 解释: 因为路径 1→3→1→1→1 的总和最小。
思路:
状态方程为:
S[i][j]=A[i][j] + max(S[i-1][j], if i>0 ; S[i][j-1], if j>0)
注意不要让矩阵的系数为负,还有二维的vector的初始化
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
int n=grid.size();//hang line
int m=grid[0].size();//lie row
int **dp=new int * [n];
for(int i=0;i<n;i++)
dp[i]=new int[m];
for(int i=0;i<n;i++)
memset(dp[i],0,sizeof(int)*m);
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(i==0)
{
if (j!=0)
dp[i][j]=dp[0][j-1]+grid[0][j];
else
dp[i][j]=grid[0][0];
}
else if(j==0)
dp[i][j]=dp[i-1][0]+grid[i][0];
else {
dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i][j];
}
}
}
return dp[n-1][m-1];
}
};
调试代码:
可以输出路径:
#include <iostream>
#include <vector>
using namespace std;
int** minPathSum(vector<vector<int>>& grid) {
int n=grid.size();//hang line
int m=grid[0].size();//lie row
int **dp=new int * [n];
for(int i=0;i<n;i++)
dp[i]=new int[m];
for(int i=0;i<n;i++)
memset(dp[i],0,sizeof(int)*m);
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(i==0)
{
if (j!=0)
dp[i][j]=dp[0][j-1]+grid[0][j];
else
dp[i][j]=grid[0][0];
}
else if(j==0)
dp[i][j]=dp[i-1][0]+grid[i][0];
else {
dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i][j];
}
}
}
return dp;
}
int main()
{
vector<vector<int>> grid(3);
for(int i=0;i<grid.size();i++)
grid[i].resize(3);
grid[0][0]=1; grid[0][1]=3; grid[0][2]=1;
grid[1][0]=1; grid[1][1]=5; grid[1][2]=1;
grid[2][0]=4; grid[2][1]=2; grid[2][2]=1;
int** dp=minPathSum(grid);
for(int i=0;i<grid.size();i++){
for(int j=0;j<grid[0].size();j++)
cout<<dp[i][j]<<" ";
cout<<endl;
}
return 0;
}