题目:
在二维网格 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)
来源:
解题思路:回溯
先找到起始位置(x,y),并统计空方格的数量,记作target,定义一个变量current记录当前经过的方格数量,从1开始累计(默认起点已遍历)。
- 递归终止条件/结果满足条件:经过的方格数量=空方格数量+2(1个起点,1个终点)
- 递归调用条件:针对上下左右方格,如果是0则递归;如果是2(即终点)仅当所有空方格遍历完成时递归。不满足条件的认为被剪枝。
本题只输出结果数量不输出结果列表,所以不再定义路径path,直接在grid上修改:递归前设置为x(只要不是0,1,2,-1即可),递归后复原。
class Solution {
public:
int result;
int m, n;
int uniquePathsIII(vector<vector<int>>& grid) {
m = grid.size();
n = grid[0].size();
// 找出起始方格,统计空方格个数
int target = 0;
int x = 0, y = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 0) target++;
if (grid[i][j] == 1) {
x = i;
y = j;
}
}
}
result = 0;
back(grid, x, y, 1, target+2);
return result;
}
void back(vector<vector<int>>& grid, int x, int y, int current, int target) {
if (current == target) {
result++;
return;
}
// 上下左右
if (x > 0) {
int t = grid[x-1][y];
if (t == 0 || (current + 1 == target && t == 2)) {
grid[x-1][y] = 3;
back(grid, x-1, y, current+1, target);
grid[x-1][y] = t;
}
}
if (x + 1 < m) {
int t = grid[x+1][y];
if (t == 0 || (current + 1 == target && t == 2)) {
grid[x+1][y] = 3;
back(grid, x+1, y, current+1, target);
grid[x+1][y] = t;
}
}
if (y > 0) {
int t = grid[x][y-1];
if (t == 0 || (current + 1 == target && t == 2)) {
grid[x][y-1] = 3;
back(grid, x, y-1, current+1, target);
grid[x][y-1] = t;
}
}
if (y + 1 < n) {
int t = grid[x][y+1];
if (t == 0 || (current + 1 == target && t == 2)) {
grid[x][y+1] = 3;
back(grid, x, y+1, current+1, target);
grid[x][y+1] = t;
}
}
}
};