【亡羊补牢】挑战数据结构与算法 第15期 LeetCode 980. 不同路径 III(递归与回溯)

仰望星空的人,不应该被嘲笑

题目描述

在二维网格 grid 上,有 4 种类型的方格:

1 表示起始方格。且只有一个起始方格。
2 表示结束方格,且只有一个结束方格。
0 表示我们可以走过的空方格。
-1 表示我们无法跨越的障碍。
返回在四个方向(上、下、左、右)上行走时,从起始方格到结束方格的不同路径的数目。

每一个无障碍方格都要通过一次,但是一条路径中不能重复通过同一个方格。

示例 1:

输入:[[1,0,0,0],[0,0,0,0],[0,0,2,-1]]
输出:2
解释:我们有以下两条路径:
1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2)
2. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2)

示例 2:

输入:[[1,0,0,0],[0,0,0,0],[0,0,0,2]]
输出:4
解释:我们有以下四条路径: 
1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2),(2,3)
2. (0,0),(0,1),(1,1),(1,0),(2,0),(2,1),(2,2),(1,2),(0,2),(0,3),(1,3),(2,3)
3. (0,0),(1,0),(2,0),(2,1),(2,2),(1,2),(1,1),(0,1),(0,2),(0,3),(1,3),(2,3)
4. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2),(2,3)

示例 3:

输入:[[0,1],[2,0]]
输出:0
解释:
没有一条路能完全穿过每一个空的方格一次。
请注意,起始和结束方格可以位于网格中的任意位置。

提示:

1 <= grid.length * grid[0].length <= 20

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/unique-paths-iii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

回溯算法,不过这道题需要我们走完所有空格,所以我们起初遍历的时候需要统计一下空格的数目,然后还有一个注意点就是重点也算是可走的路径的一个点,也需要统计进去,所以代码 cnt 值 初始化为 1

接下来就是回溯过程了,写了一个 check 函数,进行简单判断剪枝,然后就是往四个方向搜,每走一个格子就将当前格子设置为障碍(即 -1),然后搜索完后,回溯时,需要将障碍重设置为空格。

/**
 * @param {number[][]} grid
 * @return {number}
 */
var uniquePathsIII = function(grid) {
     
    let cnt = 1 // 统计地图中可走的方格个数,包括终点,故初始值为1
    let sx,sy // 记录起点坐标
    for(let i=0;i<grid.length;i++){
     
        for(let j=0;j<grid[0].length;j++){
     
            if(grid[i][j] === 1){
     
                sx = i
                sy = j
            }
            else if(grid[i][j] === 0){
     
                cnt++
            }
        }
    }
    return dfs(sx,sy,cnt,grid)
};
// 剪枝条件
let check = (sx,sy,grid) => {
     
    if(sx<0 || sx>=grid.length || sy<0 || sy>=grid[0].length || grid[sx][sy] == -1) return false
    return true
}

let dfs = (sx,sy,cnt,grid) => {
     
    if(!check(sx,sy,grid)) return 0
    if(grid[sx][sy] === 2){
      // 走到终点时,也要判断一下当前所有空格是否走完
        return cnt === 0 ? 1:0
    }
    let res = 0
    grid[sx][sy] = -1  //走过的空格进行标记,设置为障碍即可
    res += dfs(sx+1,sy,cnt-1,grid)  // 四个方向进行搜索
    res += dfs(sx,sy+1,cnt-1,grid)
    res += dfs(sx-1,sy,cnt-1,grid)
    res += dfs(sx,sy-1,cnt-1,grid)
    grid[sx][sy] = 0  // 回溯过程,不影响后续dfs
    return res
}

最后

文章产出不易,还望各位小伙伴们支持一波!

往期精选:

小狮子前端の笔记仓库

访问超逸の博客,方便小伙伴阅读玩耍~

学如逆水行舟,不进则退

你可能感兴趣的:(【亡羊补牢】挑战数据结构与算法,剪枝,算法,dfs,leetcode)