动态规划案例解析

先看一道题目

给定一个填充有非负数的m x n网格,找到一条从左上到右下的路径,该路径使沿其路径的所有数字之和最小。
注意:你只能在任何时间点向下或向右移动。

Input:
[
    [1,3,1],
    [1,5,1],
    [4,2,1]
]
Output: 7
思路就是1->3->1->1->1

关于这类型问题,比较好的做法就是使用动态规划,简单来说就是大事化小,小事化了。
把动态规划运用到这道题结题思路就是,分解、计算、合并。
先把数组设为a,横轴长度为n,竖为m
       要求出a[0][0]到a[m - 1][n - 1]最短路径。根据分解思路。只要求出a[0][1]到a[m - 1][n - 1]的最短路径和a[1][0]到a[m - 1][n - 1]的最短路径,然后这两个路径比较即可得出最短的路径。
       然后我们递归的去思考,要求出a[0][1]到a[m - 1][n - 1]最短路径,则只需要求出a[0][2]到a[m - 1][n - 1]的最短路径和a[1][1]到a[m - 1][n - 1]最短路径,两个路径相互比较取更短的即可。以此类推…

思路说完了,接下来我们看看代码
       这里说下temp数组的作用,temp数组是用来保存已经求出的改点到a[m - 1][n - 1]的最短路径的值。
例如。要求出a[0][1]到a[m - 1][n - 1]最短路径,则需要求出a[1][1]到a[m - 1][n - 1]的最短路径。然后到了求a[1][0]到a[m - 1][n - 1]最短路径,则也需要求出a[1][1]到a[m - 1][n - 1]的最短路径,因为a[1][1]到a[m - 1][n - 1]的最短路径在之前已经求出,这个时候只需要从temp数组获取即可。不需要在额外递归计算了。即直接获取temp[1][1]即可

public class MinimumPathSum {

    int[][] nums;

    int[][] temp;
    
    public int dp(int i, int j) {
        // 判断该点到目标点的最短距离是否已经求出
        if(temp[i][j] != 0) {
            return temp[i][j];
        }
        // 如果到了目标点返回0,因为目标点到目标点距离为0
        if(i == nums.length - 1 && j == nums[0].length - 1) {
            return 0;
        }
        int x = Integer.MAX_VALUE;
        int y = Integer.MAX_VALUE;
        if(j < nums[0].length - 1) {
            x = nums[i][j + 1] + dp(i, j + 1);
        }
        if(i < nums.length - 1) {
            y = nums[i + 1][j] + dp(i + 1, j);
        }
        // 对比两个距离,取更小的值
        temp[i][j] = x > y ? y : x;
        return temp[i][j];
    }

    public int minPathSum(int[][] grid) {
        nums = grid;
        int m = grid.length;
        int n = grid[0].length;
        if(m == 1 && n == 1) {
            return grid[0][0];
        }
        temp = new int[m][n];
        return dp(0, 0) + nums[0][0];
    }

    public static void main(String[] args) {
        MinimumPathSum minimumPathSum = new MinimumPathSum();
        System.out.println(minimumPathSum.minPathSum(new int[][]{{3, 2, 3}, {4, 5, 6}}));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值