【Java算法竞赛】六道题搞懂路径问题

前情提要:
所有的 题目来源 leetcode,同学可以自行通过题目跳转链接自己做题,让我们共同进步吧~
在这里插入图片描述

==================
快速跳转:
我的个人博客主页👉:Reuuse博客
新开专栏👉:Java算法专栏
❀ 感谢支持!☀

==================

请添加图片描述

不同路径

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?

在这里插入图片描述

🚀题目解析

在这里插入图片描述
即:求从左上到右下有几种方案

⭐算法原理

dp[i][j] 表示,走到[i, j]位置的时候一共有多少路径

在这里插入图片描述
状态转移方程: dp[i][j] = dp[i-1][j] + dp[i][j-1]

初始化
目的:填表不越界
开辟数组时,外围新增虚拟数组

  1. 虚拟节点的值,保证后面填表结果正确
  2. 下标的映射,横纵坐标+1
    在这里插入图片描述

填表顺序

  • 从上往下填写
  • 从左往右填写

🍃代码实现

class Solution {
    public int uniquePaths(int m, int n) {
        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];
    }
}

不同路径Ⅱ

给定一个 m x n 的整数数组 grid。一个机器人初始位于 左上角(即 grid[0][0])。机器人尝试移动到 右下角(即 grid[m - 1][n - 1])。机器人每次只能向下或者向右移动一步。

网格中的障碍物和空位置分别用 1 和 0 来表示。机器人的移动路径中不能包含 任何 有障碍物的方格。

返回机器人能够到达右下角的不同路径数量。

测试用例保证答案小于等于 2 * 109。

在这里插入图片描述

🚀题目解析
新增了障碍物的情况下有几种路径

⭐算法原理
dp[i][j] 表示,走到[i, j]位置的时候一共有多少路径
在这里插入图片描述

🍃代码实现

class Solution {
    public int uniquePathsWithObstacles(int[][] ob) {
        int m = ob.length, n = ob[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(ob[i-1][j-1] == 0) //没有障碍物
                    dp[i][j] = dp[i-1][j] + dp[i][j-1];
        return dp[m][n];
    }
}

珠宝的最大价值

现有一个记作二维矩阵 frame 的珠宝架,其中 frame[i][j] 为该位置珠宝的价值。拿取珠宝的规则为:

只能从架子的左上角开始拿珠宝
每次可以移动到右侧或下侧的相邻位置
到达珠宝架子的右下角时,停止拿取
注意:珠宝的价值都是大于 0 的。除非这个架子上没有任何珠宝,比如 frame = [[0]]。

🚀题目解析
在这里插入图片描述
在路径问题上加上了求和

⭐算法原理
dp[i][j] 表示,走到[i, j]位置的时候,此时的最大价值

在这里插入图片描述

状态转移方程: dp[i][j] = max(dp[i-1][j] + dp[i][j-1]) + g[i][j]

🍃代码实现

class Solution {
    public int jewelleryValue(int[][] grid) {
        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];
    }
}

下降路径最小和

给你一个 n x n 的 方形 整数数组 matrix ,请你找出并返回通过 matrix 的下降路径 的 最小和 。

下降路径 可以从第一行中的任何元素开始,并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列(即位于正下方或者沿对角线向左或者向右的第一个元素)。具体来说,位置 (row, col) 的下一个元素应当是 (row + 1, col - 1)、(row + 1, col) 或者 (row + 1, col + 1) 。

🚀题目解析
这个元素只能往 左下 下 右下 的方式走

在这里插入图片描述

⭐算法原理
dp[i][j] 表示,走到[i, j]位置时,最小的下降路径

在这里插入图片描述
状态转移方程: dp[i][j] = min(x, y, z) + m[i][j]

初始化
在这里插入图片描述

  • 加上一行,加上两列
  • 所有位置 改为 +∞
  • 第一行改为 0

填表顺序 :从上往下
返回值:最后一行的最小值

🍃代码实现

class Solution {
    public int minFallingPathSum(int[][] matrix) {
        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;
    }
}

最小路径和

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

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

🚀题目解析

在这里插入图片描述

⭐算法原理
dp[i][j] 表示,到达[i, j]位置时,最小路径和
在这里插入图片描述

状态转移方程: dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + g[i][j]

初始化:
在这里插入图片描述
填表顺序: 从上往下,从左往右

返回值: dp[m][n]

🍃代码实现

class Solution {
    public int minPathSum(int[][] grid) {
        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];
    }
}

地下城游戏

恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。

骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。

有些房间由恶魔守卫,因此骑士在进入这些房间时会失去健康点数(若房间里的值为负整数,则表示骑士将损失健康点数);其他房间要么是空的(房间里的值为 0),要么包含增加骑士健康点数的魔法球(若房间里的值为正整数,则表示骑士将增加健康点数)。

为了尽快解救公主,骑士决定每次只 向右向下 移动一步。

返回确保骑士能够拯救到公主所需的最低初始健康点数。

注意:任何房间都可能对骑士的健康点数造成威胁,也可能增加骑士的健康点数,包括骑士进入的左上角房间以及公主被监禁的右下角房间。

🚀题目解析
在这里插入图片描述

⭐算法原理

  1. 以某个位置为结尾
    dp[i][j] 表示,从起点出发,到达[i, j]位置时,所需最低初始健康点数

可以发现状态一直在更改,完全推不出来,所以需要另一个方式

  1. 以某个位置为起点
    dp[i][j] 表示,从[i, j]位置出发,到达终点,所需最低初始健康点数

在这里插入图片描述
状态转移方程: dp[i][j] = min(dp[i][j=1], dp[i=][j]) - d[i][j]

特殊情况: 若d[i][j] 值过大导致结果大于0;且 dp[i][j] 是处于负数的情况下,则不符合题意(如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。)

  • 增加判断:dp[i][j] = max(1, dp[i][j])

初始化:
在这里插入图片描述
填表顺序: 从下往上,从右往左
返回值: dp[0][0]

🍃代码实现

class Solution {
    public int calculateMinimumHP(int[][] d) {
        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];
    }
}

一个小小的赞是对我大大滴支持~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Reuuse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值