当前位置: 首页 > article >正文

动态规划 之 路径问题 算法专题

一. 不同路径

不同路径

  1. 状态表示
    dp[i][j] 表示走到[i][j]位置, 有几种不同的路径
  2. 状态转移方程
    以离[i][j] 最近的位置划分问题
    1.从[i - 1][j] 到[i][j], 到[i][j]位置的不同路径数 就是和 到[i - 1][j]位置的不同路径数相同, 即dp[i][j] = dp[i - 1][j]
    2.从[i][j - 1] 到[i][j], 到[i][j]位置的不同路径数 就是和 到[i ][j - 1]位置的不同路径数相同, 即dp[i][j] = dp[i][j - 1]
  • dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
  1. 初始化
    使用优化的思想进行初始化, 添加虚拟节点
    在第一行和第一列的位置填表时会发生越界
    所以需要添加一行一列
    在这里插入图片描述
    我们只需要像上表一样初始化虚拟节点, 就可以正确的进行填表

  2. 填表顺序
    从上往下 从左往右

  3. 返回值
    返回dp[m][n]

class Solution {
    public int uniquePaths(int m, int n) {
        //1. 创建表
        //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];
    }
}

二. 不同路径II

不同路径II

  1. 状态表示
    dp[i][j] 表示走到[i][j]位置, 有几种不同的路径
  2. 状态转移方程
    以离[i][j] 最近的位置划分问题
    1.从[i - 1][j] 到[i][j], 到[i][j]位置的不同路径数 就是和 到[i - 1][j]位置的不同路径数相同, 即dp[i][j] = dp[i - 1][j]
    2.从[i][j - 1] 到[i][j], 到[i][j]位置的不同路径数 就是和 到[i ][j - 1]位置的不同路径数相同, 即dp[i][j] = dp[i][j - 1]
    但是如果此时的[i][j]是障碍物, 那么到达这个位置的路径数就为0, 所以dp[i][j] = 0
  • dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
  1. 初始化
    使用优化的思想进行初始化, 添加虚拟节点
    在第一行和第一列的位置填表时会发生越界
    所以需要添加一行一列
    在这里插入图片描述
    我们只需要像上表一样初始化虚拟节点, 就可以正确的进行填表

  2. 填表顺序
    从上往下 从左往右

  3. 返回值
    返回dp[m][n]

class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
         //1. 创建表
        //2. 初始化
        //3. 填表
        //4. 返回值
        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;
        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++){
                if(obstacleGrid[i - 1][j - 1] == 1) {
                    dp[i][j] = 0;
                }else{
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                }
            }
        }
        return dp[m][n];
    }
}

三. 珠宝的最高价值

珠宝的最高价值

  1. 状态表示
    dp[i][j] 表示走到[i][j]位置, 获得的珠宝的最高价值是多少
  2. 状态转移方程
    以离[i][j] 最近的位置划分问题
    到[i][j]位置的获得的珠宝的最高价值 就是到[i - 1][j]位置的获得的珠宝的最高价值 与 到[i][j - 1]位置的获得的珠宝的最高价值 的最大值, 然后加上[i][j]位置本来的价值
  • dp[i][j] = max(dp[i - 1][j] + dp[i][j - 1]) + frame[i - 1][j - 1](采用优化的思想, 与原下标对应要 - 1)
  1. 初始化
    使用优化的思想进行初始化, 添加虚拟节点
    在第一行和第一列的位置填表时会发生越界
    所以需要添加一行一列
    我们只需要将虚拟节点都设为0即可
  2. 填表顺序
    从上往下 从左往右
  3. 返回值
    返回dp[m][n]
class Solution {
    public int jewelleryValue(int[][] frame) {
        //1. 创建dp
        //2. 初始化
        //3. 填表
        //4. 返回值
        int m = frame.length;
        int n = frame[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 - 1][j], dp[i][j - 1]) + frame[i - 1][j - 1];
            }
        }
        return dp[m][n];
    }
}

四. 下降路径最小和

下降路径最小和

  1. 状态表示
    dp[i][j] 表示走到[i][j]位置, 路径的最小和
  2. 状态转移方程
    以离[i][j] 最近的位置划分问题
    到[i][j]位置的路径的最小和 就是到[i - 1][j - 1]位置路径的最小和 与 到[i - 1][j]位置路径的最小和 与 [i - 1][j + 1]位置路径的最小和 的最小值, 然后加上[i][j]位置本来的值
  • dp[i][j] = Math.min(Math.min(dp[i - 1][j - 1], dp[i - 1][j]), dp[i - 1][j + 1]) + matrix[i - 1][j - 1](采用优化的思想, 与原下标对应要 - 1)
  1. 初始化
    使用优化的思想进行初始化, 添加虚拟节点
    在第一行和第一列和最后一列的位置填表时会发生越界
    所以需要添加一行两列
    我们需要将虚拟节点都设为最大值, 防止对原来的数进行干扰
  2. 填表顺序
    从上往下 从左往右
  3. 返回值
    返回最后一行中的最小值
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] = Integer.MAX_VALUE;
            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(Math.min(dp[i - 1][j - 1], dp[i - 1][j]), dp[i - 1][j + 1]) + matrix[i - 1][j - 1];
            }
        }
        int min = Integer.MAX_VALUE;
        for(int j = 1; j <= n; j++){
            min = Math.min(min, dp[n][j]);
        }
        return min;
    }
}

五. 最小路径和

最小路径和

  1. 状态表示
    dp[i][j] 表示走到[i][j]位置, 路径的最小和
  2. 状态转移方程
    以离[i][j] 最近的位置划分问题
    到[i][j]位置的路径的最小和 就是到[i - 1][j]位置路径的最小和 与 [i][j - 1]位置路径的最小和 的最小值, 然后加上[i][j]位置本来的值
  • dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1](采用优化的思想, 与原下标对应要 - 1)
  1. 初始化
    使用优化的思想进行初始化, 添加虚拟节点
    在第一行和第一列的位置填表时会发生越界
    所以需要添加一行一列
    我们需要将虚拟节点设为最大值, 但是[0][1]位置的值要设为0, 防止对原来的数进行干扰
  2. 填表顺序
    从上往下 从左往右
  3. 返回值
    dp[m][n]
class Solution {
    public int minPathSum(int[][] grid) {
        // 1. 创建dp
        // 2. 初始化
        // 3. 填表
        // 4. 返回值
        int m = grid.length;
        int n = grid[0].length;
        int[][] dp = new int[m + 1][n + 1];
        for (int i = 0; i <= m; i++) {
            dp[i][0] = Integer.MAX_VALUE;
        }
        for (int j = 0; j <= n; j++) {
            dp[0][j] = Integer.MAX_VALUE;
        }
        dp[0][1] = 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];
    }
}

六. 地下城游戏

地下城游戏

  1. 状态表示
    dp[i][j] 如果表示走到[i][j]位置, 所需要的最小血量, 是没办法完成这道题的, 因为, 每走一步, 所需的最小血量都在更新
    所以dp[i][j] 表示从[i][j]位置开始, 所需要的最小血量
  2. 状态转移方程
    以离[i][j] 最近的位置划分问题
    1.[i][j]位置所需要的最小血量 + [i][j]位置需要加或减的血量 一定是要 >= 到[i + 1][j]位置所需要的最小血量, 才能保证走下一个位置的时候不会死, 所以dp[i][j] = dp[i + 1][j] - 原表的[i][j]
    2.[i][j]位置所需要的最小血量 + [i][j]位置需要加或减的血量 一定是要 >= 到[i][j + 1]位置所需要的最小血量, 才能保证走下一个位置的时候不会死, 所以dp[i][j] = dp[i][j + 1] - 原表的[i][j]
  • dp[i][j] = Math.min(dp[i + 1][j], dp[i][j + 1]) - 原表的[i][j]
    但是我们得出的dp[i][j] 必须是>0的, 如果<0, 就设为1, 所需要的最低血量
  1. 初始化
    使用优化的思想进行初始化, 添加虚拟节点
    在最后一行和最后一列的位置填表时会发生越界
    所以需要添加一行一列
    我们需要将虚拟节点设为最大值, 但是[m][n - 1]位置 和[m - 1][n]位置 的值要设为1, 所需要的最低血量
  2. 填表顺序
    从下往上 从右往左
  3. 返回值
    dp[0][0]
class Solution {
    public int calculateMinimumHP(int[][] dungeon) {
          // 1. 创建dp
        // 2. 初始化
        // 3. 填表
        // 4. 返回值
        int m = dungeon.length;
        int n = dungeon[0].length;
        int [][] dp = new int[m + 1][n + 1];
        for(int i = m; i >= 0; i--){
            dp[i][n] = Integer.MAX_VALUE;
        }
        for(int j = n; j >= 0; j--){
            dp[m][j] = 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 + 1][j], dp[i][j + 1]) - dungeon[i][j];
                dp[i][j] = Math.max(1, dp[i][j]);
            }
        }
        return dp[0][0];
    }
}

http://www.kler.cn/a/383350.html

相关文章:

  • 越权访问漏洞
  • SpringBoot3集成Junit5
  • nuiapp vue3 uni-ui uni.uploadFile 图片上传
  • 「Mac畅玩鸿蒙与硬件16」鸿蒙UI组件篇6 - List 和 Grid 组件展示数据列表
  • 第9天:网络编程-补充材料——‘MainActivity.kt‘解读
  • 【google play】使用Java接入谷歌支付流程
  • 【TS】九天学会TS语法——1.TypeScript 是什么
  • sls日志服务采集json格式日志
  • HE-Drive:Human-Like End-to-End Driving with Vision Language Models
  • [蓝桥杯算法从小白到大牛]动态规划第二讲:三步问题
  • RK3568 Android12跳过认证 预置谷歌服务GMS
  • 【系统架构设计师】高分论文:论高并发下的高可用性技术
  • 未来已来:AI编程——重塑软件开发的新纪元
  • (十四)JavaWeb后端开发——MyBatis
  • 怎么查看navicat的数据库密码
  • 国家宠物美容师职业技能等级评价(高级)理论考试题
  • ac8257 android 9 lk upgrade升级后分区表错误问题
  • ​Java面试经典 150 题.P13. 罗马数字转整数(012)​
  • 为什么要学习 Java 编程
  • 人工智能技术:未来生活的“魔法师”
  • NewStar CTF 2024 misc WP
  • 基于SSD模型的路面坑洼检测系统,支持图像、视频和摄像实时检测【pytorch框架、python源码】
  • 502 Bad Gateway 错误详解:从表现推测原因,逐步排查直至解决
  • Vue 2 + JavaScript + vue-count-to 集成案例
  • Ubuntu系统如何实现键盘按键映射到其他按键(以 Ctrl+c 映射到 F3,Ctrl+v 映射到 F4 为例)
  • python传递json参数给php