首页 > 其他 > 详细

[LeetCode] 64. 最小路径和 ☆☆☆(动态规划)

时间:2019-11-14 15:35:36      阅读:84      评论:0      收藏:0      [点我收藏+]

描述

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

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

示例:

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

解析

由于我们的目的是从左上角到右下角,最小路径和是多少,那我们就定义 dp[i] [j]的含义为:当从左上角走到(i, j) 这个位置时,最下的路径和是 dp[i] [j]。那么,dp[m-1] [n-1] 就是我们要的答案了。

想象以下,要怎么样才能到达 (i, j) 这个位置?由于可以向下走或者向右走,所以有两种方式到达

一种是从 (i-1, j) 这个位置走一步到达

一种是从(i, j - 1) 这个位置走一步到达

不过这次不是计算所有可能路径,而是计算哪一个路径和是最小的,那么我们要从这两种方式中,选择一种,使得dp[i] [j] 的值是最小的,显然有

dp[i] [j] = min(dp[i-1][j],dp[i][j-1]) + arr[i][j];// arr[i][j] 表示网格中的值

初始值:

当 dp[i] [j] 中,如果 i 或者 j 有一个是 0,那么还能使用关系式吗?答是不能的。

因为这个时候把 i - 1 或者 j - 1,就变成负数了,数组就会出问题了,所以我们的初始值是计算出所有的 dp[0] [0….n-1] 和所有的 dp[0….m-1] [0]。这个还是非常容易计算的,相当于图中的最上面一行和左边一列。因此初始值如下:

dp[0] [j] = arr[0] [j] + dp[0] [j - 1]; // 相当于第一行,只能一直往左走

dp[i] [0] = arr[i] [0] + dp[i - 1] [0]; // 相当于第一列,只能一直往下走

代码

public int minPathSum(int[][] grid) {
        if (null == grid || grid.length <= 0) {
            return 0;
        }
        int[][] dp = new int[grid.length][grid[0].length];
        dp[0][0] = grid[0][0];
        for (int i = 1; i < dp.length; i++) {
            dp[i][0] = dp[i - 1][0] + grid[i][0];
        }
        for (int i = 1; i < dp[0].length; i++) {
            dp[0][i] = dp[0][i - 1] + grid[0][i];
        }
        for (int ii = 1; ii < dp.length; ii++) {
            for (int kk = 1; kk < dp[0].length; kk++) {
                dp[ii][kk] = Math.min(dp[ii - 1][kk], dp[ii][kk - 1]) + grid[ii][kk];
            }
        }
        return dp[grid.length - 1][grid[0].length - 1];
    }

 

[LeetCode] 64. 最小路径和 ☆☆☆(动态规划)

原文:https://www.cnblogs.com/fanguangdexiaoyuer/p/11857564.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!