LeetCode 980. 不同路径 III
题目描述
在二维网格 grid
上,有 4 种类型的方格:
1
表示起始方格。且只有一个起始方格。 2
表示结束方格,且只有一个结束方格。 0
表示我们可以走过的空方格。 -1
表示我们无法跨越的障碍。返回在四个方向(上、下、左、右)上行走时,从起始方格到结束方格的不同路径的数目。
每一个无障碍方格都要通过一次,但是一条路径中不能重复通过同一个方格。
示例 1:
javascript
输入:[[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:
javascript
输入:[[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:
javascript
输入:[[0,1],[2,0]]
输出:0
解释:
没有一条路能完全穿过每一个空的方格一次。
请注意,起始和结束方格可以位于网格中的任意位置。
提示:
javascript
1 <= grid.length * grid[0].length <= 20;
来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/unique-paths-iii 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
回溯算法,不过这道题需要我们走完所有空格,所以我们起初遍历的时候需要统计一下空格的数目,然后还有一个注意点就是重点也算是可走的路径的一个点,也需要统计进去,所以代码 cnt
值 初始化为 1
接下来就是回溯过程了,写了一个 check
函数,进行简单判断剪枝,然后就是往四个方向搜,每走一个格子就将当前格子设置为障碍(即 -1
),然后搜索完后,回溯时,需要将障碍重设置为空格。
javascript
/**
* @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;
};
cpp
class Solution {
public:
int uniquePathsIII(vector<vector<int>>& grid) {
int cnt = 1; // 统计地图中可走的方格个数,包括终点,故初始值为1
int sx, sy; // 记录起点坐标
for (int i = 0; i < grid.size(); i++) {
for (int j = 0; j < grid[0].size(); j++) {
if (grid[i][j] == 1) {
sx = i;
sy = j;
} else if (grid[i][j] == 0) {
cnt++;
}
}
}
return dfs(sx, sy, cnt, grid);
}
// 剪枝条件
bool check(int sx, int sy, vector<vector<int>>& grid) {
if (sx < 0 || sx >= grid.size() || sy < 0 || sy >= grid[0].size() || grid[sx][sy] == -1) return false;
return true;
}
int dfs(int sx, int sy, int cnt, vector<vector<int>>& grid) {
if (!check(sx, sy, grid)) return 0;
if (grid[sx][sy] == 2) { // 走到终点时,也要判断一下当前所有空格是否走完
return cnt == 0 ? 1 : 0;
}
int 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;
}
};
java
class Solution {
int res = 0;
int cnt = 1;
int sx, sy;
public int uniquePathsIII(int[][] grid) {
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (grid[i][j] == 1) {
sx = i;
sy = j;
} else if (grid[i][j] == 0) {
cnt++;
}
}
}
dfs(sx, sy, grid);
return res;
}
public void dfs(int sx, int sy, int[][] grid) {
if (sx < 0 || sx >= grid.length || sy < 0 || sy >= grid[0].length || grid[sx][sy] == -1) return;
if (grid[sx][sy] == 2) {
res += cnt == 0 ? 1 : 0;
return;
}
grid[sx][sy] = -1;
cnt--;
dfs(sx + 1, sy, grid);
dfs(sx, sy + 1, grid);
dfs(sx - 1, sy, grid);
dfs(sx, sy - 1, grid);
grid[sx][sy] = 0;
cnt++;
}
}
python
class Solution:
def uniquePathsIII(self, grid: List[List[int]]) -> int:
cnt = 1
sx, sy = 0, 0
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == 1:
sx, sy = i, j
elif grid[i][j] == 0:
cnt += 1
def dfs(sx, sy, cnt):
if sx < 0 or sx >= len(grid) or sy < 0 or sy >= len(grid[0]) or grid[sx][sy] == -1:
return 0
if grid[sx][sy] == 2:
return 1 if cnt == 0 else 0
grid[sx][sy] = -1
cnt -= 1
res = dfs(sx + 1, sy, cnt) + dfs(sx, sy + 1, cnt) + dfs(sx - 1, sy, cnt) + dfs(sx, sy - 1, cnt)
grid[sx][sy] = 0
cnt += 1
return res
return dfs(sx, sy, cnt)
javascript
学如逆水行舟,不进则退