LeetCode中国,https://leetcode-cn.com/problems/minimum-path-sum/。
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。
LeetCode 给出本题难度中等。一个非常经典的动态规划问题。
本题的核心是:每次只能向下或者向右移动一步。我们可以使用动态规划自顶向下生成的方法来分析问题。
根据题目的意思,我们从数组的左上角出发,也就是(0, 0)这个位置出发。根据规则,我们只能向下或者向右移动一次,一次走一步。如下图所示。
根据这个前提条件,我们需要构造一个动态规划数组,也就是 DP 数组,用来描述走到 i, j 这个位置的最小代价。
原始数据的初始状态如下图所示。
DP 数组的初始状态可以这样推导出。
1、dp[0][0] 这个点。自然最小代价就是数组的(0,0)点的值,也就是 dp[0][0]=grid[0][0]=1。
2、第 0 行。根据行走规则,只能向右移动。也就意味着 dp[0][j] = dp[0][j-1]+grid[0][j-1],因为我们是从右边移动过来,所以代价就是右边 dp 数据加上 grid 本格的数据。
3、第 0 列。根据行走规则,只能向下移动。也就意味着 dp[i][0] = dp[i-1][0]+grid[i-1][0],因为我们是从上边移动过来,所以代价就是上边 dp 数据加上 grid 本格的数据。
这样,我们就得到了 DP 数组对应的初始状态。
这样,假设一个位置为(i,j),根据移动规则,要走到这个位置,只有两个可能:1、从(i-1, j)向下走一步;2、从(i, j-1)向右走一步。因此我们可以推导出 dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + gird[i][j]。
1、(1, 1)点。从(0, 1)点走过来的代价是 4+5=9;从(1, 0)点走过来的代价是 2+5=7。因此最小代价为 7。
2、(1, 2)点。从(0, 2)点走过来的代价是 5+1=6;从(1, 1)点走过来的代价是 7+1=8。因此最小代价为 6。
3、(2, 1)点。从(1, 1)点走过来的代价是 7+2=9;从(2, 0)点走过来的代价是 6+2=8。因此最小代价为 8。
4、(2, 2)点。从(1, 2)点走过来的代价是 6+1=7;从(2, 1)点走过来的代价是 8+1=9。因此最小代价为 7。
这样,利用一个两重循环,我们可以推导出完整的 DP 数组。对应数据如下:
这样,我们就得到最终的最小代价为 dp[2][2]=7。
class Solution {
public:
int minPathSum(vector>& grid) {
//获取行
int row = grid.size();
int col = grid[0].size();
//特殊处理
if (0==row || 0==col) {
return 0;
}
//DP数组
auto dp = vector>(row, vector(col));
//初始化DP
dp[0][0] = grid[0][0];
//第0行数据
int i,j;
for (j=1; j