19.动态规划之路径问题2

1.不同路径

62. 不同路径 - 力扣(LeetCode)

题目解析

算法思路:

1. 状态表示:

对于这种「路径类」的问题,我们的状态表⽰⼀般有两种形式:
i. [i, j] 位置出发,巴拉巴拉;
ii. 从起始位置出发,到达 [i, j] 位置,巴拉巴拉。
这⾥选择第⼆种定义状态表⽰的⽅式:
dp[i][j] 表⽰:⾛到 [i, j] 位置处,⼀共有多少种⽅式。

2. 状态转移⽅程:

简单分析⼀下。如果 dp[i][j] 表⽰到达 [i, j] 位置的⽅法数,那么到达 [i, j] 位置之
前的⼀⼩步,有两种情况:
i. [i, j] 位置的上⽅( [i - 1, j] 的位置)向下⾛⼀步,转移到 [i, j] 位置;
ii. [i, j] 位置的左⽅( [i, j - 1] 的位置)向右⾛⼀步,转移到 [i, j] 位置。
由于我们要求的是有多少种⽅法,因此状态转移⽅程就呼之欲出了: dp[i][j] = dp[i - 1]
[j] + dp[i][j - 1]

3. 初始化:

可以在最前⾯加上⼀个「辅助结点」,帮助我们初始化。使⽤这种技巧要注意两个点:
i. 辅助结点⾥⾯的值要「保证后续填表是正确的」;
ii. 「下标的映射关系」。
在本题中,「添加⼀⾏」,并且「添加⼀列」后,只需将 dp[0][1] 的位置初始化为 1 即可。

4. 填表顺序:

根据「状态转移⽅程」的推导来看,填表的顺序就是「从上往下」填每⼀⾏,在填写每⼀⾏的时候 「从左往右」。

5. 返回值:

根据「状态表⽰」,我们要返回 dp[m][n] 的值。
class Solution {
    public int uniquePaths(int m, int n) {
        // 1. 创建 dp 表
        // 2. 初始化
        // 3. 填表
        // 4. 返回值
        int[][] dp = new int[m + 1][n + 1];
        dp[0][1] = 1;
        for (int i = 1; i <= m; i++) // 从上往下每⼀⾏
            for (int j = 1; j <= n; j++) // 从左往右填写每⼀⾏
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];

        return dp[m][n];
    }
}

 2.不同路径2

63. 不同路径 II - 力扣(LeetCode)

题目解析

此时有障碍物

算法思路

主要关注的是机器人刚开始站的位置

class Solution {
    public int uniquePathsWithObstacles(int[][] ob) {
        // 1. 创建 dp 表
        // 2. 初始化
        // 3. 填表
        // 4. 返回值
        int m = ob.length, n = ob[0].length;
        int[][] dp = new int[m + 1][n + 1];
        dp[1][0] = 1;
        for (int i = 1; i <= m; i++)
            for (int j = 1; j <= n; j++)
                if (ob[i - 1][j - 1] == 0)
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
        return dp[m][n];
    }
}

 3.礼物的最大价值

LCR 166. 珠宝的最高价值 - 力扣(LeetCode)

题目解析

算法思路

class Solution {
    public int maxValue(int[][] grid) {
        // 1. 创建 dp 表
        // 2. 初始化
        // 3. 填表
        // 4. 返回值
        int m = grid.length, n = grid[0].length;
        int[][] dp = new int[m + 1][n + 1];
        for (int i = 1; i <= m; i++)
            for (int j = 1; j <= n; j++)
                dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]) + grid[i - 1][j - 1];
        return dp[m][n];
    }
}

 4.下降路径最小和

931. 下降路径最小和 - 力扣(LeetCode)

题目解析

算法思路

class Solution {
    public int minFallingPathSum(int[][] matrix) {
        // 1. 创建 dp 表
        // 2. 初始化
        // 3. 填表
        // 4. 返回结果
        int n = matrix.length;
        int[][] dp = new int[n + 1][n + 2];
        for (int i = 1; i <= n; i++)
            dp[i][0] = dp[i][n + 1] = Integer.MAX_VALUE;

        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                dp[i][j] = Math.min(dp[i - 1][j], Math.min(dp[i - 1][j - 1], dp[i - 1][j + 1])) + matrix[i - 1][j - 1];
        int ret = Integer.MAX_VALUE;
        for (int j = 1; j <= n; j++)
            ret = Math.min(ret, dp[n][j]);
        return ret;
    }
}

5.最小路径和 

64. 最小路径和 - 力扣(LeetCode)

 题目解析

 算法思路

 

class Solution {
    public int minPathSum(int[][] grid) {
        // 1. 创建 dp 表
        // 2. 初始化
        // 3. 填表
        // 4. 返回值
        int m = grid.length, n = grid[0].length;
        int[][] dp = new int[m + 1][n + 1];
        for (int j = 0; j <= n; j++)
            dp[0][j] = Integer.MAX_VALUE;
        for (int i = 0; i <= m; i++)
            dp[i][0] = Integer.MAX_VALUE;
        dp[0][1] = dp[1][0] = 0;
        for (int i = 1; i <= m; i++)
            for (int j = 1; j <= n; j++)
                dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1];
        return dp[m][n];
    }
}

 6.地下城游戏

. - 力扣(LeetCode)

题目解析

算法原理

class Solution {
    public int calculateMinimumHP(int[][] d) {
        // 1. 创建 dp 表
        // 2. 初始化
        // 3. 填表
        // 4. 返回值
        int m = d.length, n = d[0].length;
        int[][] dp = new int[m + 1][n + 1];
        for (int j = 0; j <= n; j++)
            dp[m][j] = Integer.MAX_VALUE;
        for (int i = 0; i <= m; i++)
            dp[i][n] = Integer.MAX_VALUE;
        dp[m][n - 1] = dp[m - 1][n] = 1;
        for (int i = m - 1; i >= 0; i--)
            for (int j = n - 1; j >= 0; j--) {
                dp[i][j] = Math.min(dp[i][j + 1], dp[i + 1][j]) - d[i][j];
                dp[i][j] = Math.max(dp[i][j], 1);
            }
        return dp[0][0];
    }
}

  • 24
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值