网格问题(回溯/DP):最短路径(排除障碍物)+路径数量+路径最大/小和+判断路径存在

一、网格中的最短路径

1.1 可以消除障碍物

LeetCode1293:网格中的最短路径
给你一个 m * n 的网格,其中每个单元格不是 0(空)就是 1(障碍物)。每一步,您都可以在空白单元格中上、下、左、右移动。如果您 最多 可以消除 k 个障碍物,请找出从左上角 (0, 0) 到右下角 (m-1, n-1) 的最短路径,并返回通过该路径所需的步数。如果找不到这样的路径,则返回 -1。
在这里插入图片描述

class Solution {
   
   
	public static void main(String[] args) {
   
   
        Scanner sc = new Scanner(System.in);
        int m = sc.nextInt();//网格的长
		int n = sc.nextInt();//网格的宽
		int k = sc.nextInt();
        
        int[][] grid = new int[m][n];

        for(int i=0;i<m;i++){
   
   
            for(int j=0;j<n;j++){
   
   
                grid[i][j] = sc.nextInt();
            }
        }
        System.out.println(shortestPath(grid,k));
    }
    public int shortestPath(int[][] grid, int k) {
   
   
        int m = grid.length;
        int n = grid[0].length;
        if(k >= m + n -3) return m + n - 2;
        boolean[][] visited = new boolean[m][n];
        int res = backtrack(grid,0,0,m,n,0,k,visited);
        return res == Integer.MAX_VALUE ? -1 : res;
    }

    public int backtrack(int[][] grid,int i,int j,int m,int n,int count,int k,boolean[][] visited){
   
   
        if(i < 0 || i >= m || j < 0 || j >= n) return Integer.MAX_VALUE;//递归出口
        if(i == m-1 && j == n-1) return count;//结果
        if(visited[i][j]) return Integer.MAX_VALUE;
        //排除障碍物
        if(grid[i][j] == 1){
   
   
            if(k > 0) k--;
            else return Integer.MAX_VALUE;
        }
        visited[i][j] = true;
        //取4个方向可能路径的最小值返回
        int min4 = Integer.MAX_VALUE;
        min4 = Math.min(min4,backtrack(grid,i-1,j,m,n,count+1,k,visited));
        min4 = Math.min(min4,backtrack(grid,i+1,j,m,n,count+1,k,visited));
        min4 = Math.min(min4,backtrack(grid,i,j-1,m,n,count+1,k,visited));
        min4 = Math.min(min4,backtrack(grid,i,j+1,m,n,count+1,k,visited));
        //回溯
        visited[i][j] = false;
        return min4;
    }
}

【法二】visited访问标记数组三维扩展 (用于比较)

本题比较麻烦些,增加了障碍物且可以有k次机会消除,单纯有障碍物就是标准的BFS处理即可,但有k次消除障碍物,就需要增加一个维度来记录同一个节点被访问的时候 已经使用消除障碍物的次数。:

链接:作者:jin-129

public int shortestPath(int[][] grid, int k) {
   
   
        int m = grid.length;
        int n = grid[0].length;
        // 非法参数处理
        if (validateInputParams(k, m, n)) {
   
   
            return -1;
        }
        // 特殊场景处理
        if (m == 1 && n == 1) {
   
   
            return 0;
        }
        // BFS搜索节点访问标识, 此题要求有k个消除障碍的机会,所以每个节点除了标记是否被访问过
        // 还要记录搜索到此节点时消除了几个障碍。消除相同障碍的下一层节点 可以剪枝(因为有相同代价更早的节点了)
        // 例子:k=1, BFS是按层级来的,绕道的层级扩展越多
        // 坐标(0,2)可以为消除(0,1)障碍过来的 visited[0][2][1] = 1,搜索层级为2
        // 也可能为不消除任何障碍过来的 visited[0][2][0] = 1,层级为6,为扩展搜索不通障碍消除数提供区分
        // 0 1 0 0 0 1 0 0
        // 0 1 0 1 0 1 0 1
        // 0 0 0 1 0 0 1 0

        // 二维标记位置,第三维度标记 到此节点的路径处理障碍总个数
        int[][][] visited = new int[m][n][k+1];
        // 初始步数为0,m=n=1的特殊场景已处理
        int minSteps = 0;
        // 初始位置标记已访问
        visited[0][0][0
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值