力扣原题链接,点击跳转。
有一个m×n的网格grid,网格中有数字。请找出一条从左上角到右下角的路径,使得路径上的值的和最小。每次只能向下或向右走。
我们用动态规划的思想来解决这个问题。首先创建dp表。先确定状态表示,我们用dp[i][j]表示从左上角到(i,j)的最小路径和。接着推导状态转移方程,考虑到达(i,j)最近的一步,只能从(i-1,j)或(i,j-1)出发才能到达(i,j),故有dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i][j]。
考虑初始化的问题,由于dp[i][j]只和上边和左边的值相关,所以需要初始化最上面一行和最左边一列。
? ? ? ? ?
?
?
我们在最上面和最左边多加上一行一列。
* * * * * *
* ? ? ? ? ?
* ?
* ?
左上角的?的值应为grid这个位置的值。为了满足状态转移方程,就把这个?上边和左边的位置初始化成0。
* 0 * * * *
0 ? ? ? ? ?
* ?
* ?
接着考虑其他?的值。为了让求min(dp[i-1][j],dp[i][j-1])时,?的值不会影响结果,故*位置应全部初始化为+∞。注意此时dp表和grid的对应关系:dp表的(i,j)对应grid的(i-1,j-1)。由于dp表(i,j)位置的值只和左边和上边的值相关,故应从上往下填每一行,每一行从左往右填表,确保填(i,j)时,它上边和左边的值已经准备好了。最后应返回dp[m][n],对应grid的(m-1,n-1)。
class Solution
{
public:int minPathSum(vector<vector<int>>& grid){// 创建dp表int m = grid.size(), n = grid[0].size();vector<vector<int>> dp(m + 1, vector<int>(n + 1, INT_MAX));// 初始化dp[0][1] = dp[1][0] = 0;// 填表for (int i = 1; i <= m; i++)for (int j = 1; j <= n; j++)dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1];return dp[m][n];}
};