「动态规划」「leetcode」64.最小路径和

647 阅读2分钟

原题

给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:每次只能向下或者向右移动一步。

示例:

输入:
[
  [1,3,1],
  [1,5,1],
  [4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。

思路

解决DP问题,最重要的是找出状态转移方程,我们下面举一个例子,尝试找出本题的状态转移方程

第一步

对于grid[0][0]而言无论,如何行动,路径的和一定等于1

1.png

第二步

由于我们只能向下和向右走,所以。

i = 0时,路径和一定等于grid[i][j] + grid[i][j - 1],因为我们只能往右走

j = 0时,路径和一定等于grid[i][j] + grid[i -1][j],因为我们只能往下走

我们可以得到如下的grid

2.png

3.png

第三步

对于i !=0 && j !== 0的情况,我们到达此点的方式,可以从上面,也可以从左面。我们应该选择两种方式中和最小的方式

4.png

5.png

第n步 ……依次类推

通过上面的分析,我们可以获得如下状态转移方程, 接下来我们可以轻松列出我们的代码了

QQ20190905-235609@2x.png

代码


/**
 * @param {number[][]} grid
 * @return {number}
 */
var minPathSum = function(grid) {
    if (grid.length === 0) {
        return 0
    }
       
    const dp = []
    const w = grid[0].length
    const h = grid.length
    
    for (let i = 0; i < h; i++) {
        for (let j = 0; j < w; j++) {
            if (!dp[i]) {
                dp[i] = []
            }
            let m, n
            if (i === 0) {
                m = j - 1 < 0 ? 0 : dp[i][j - 1]
                n = grid[i][j]
                dp[i][j] = m + n
                continue
            }
            if (j === 0) {
                m = i - 1 < 0 ? 0 : dp[i - 1][j]
                n = grid[i][j]
                dp[i][j] = m + n
                continue
            }
            dp[i][j] = Math.min(
                grid[i][j] + dp[i - 1][j],
                grid[i][j] + dp[i][j - 1]
            )
        }
    }
    
    return dp[h - 1][w - 1]
};