题目来源
题目描述
class Solution {
public:
int uniquePathsIII(vector<vector<int>>& grid) {
}
};
题目解析
题意
- 每个无障碍方格都要通过一次:把所有能走的格子都走完而且刚好到达终点的路径
- 每个格子只能都一次,意味着不能走回头路
那么:怎么判断是否已经走完了所有格子呢?
- 可以统计所有可以通过的格子数量,假设为count。
- 然后正常的回溯,当步骤为count + 1时,(到达终点的步数正是走完了所有可通过格子再加一),如果当前刚好在终点上,那么就形成了有效路径。
怎么做到不走回头路呢?
- 当到达一个可走的格子时,需要先标记它已经走过。在四个方向都尝试完了之后,才恢复现场
class Solution {
std::vector<std::vector<int>> directions {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};//四个方向
/**
* @param x 坐标的row
* @param y 坐标的col
* @param counts 当前路径所剩的长度
* @param grid 矩阵
* @return
*/
int dfs(int x, int y, int counts, vector<vector<int>>& grid){
int m = grid.size(), n = grid[0].size();
// 切记 不合法索引一定要从头就掐除,因为它最容易导致报错;
// 当前位置是障碍(即值为 -1)跳出;
if (x < 0 || x == m || y < 0 || y == n || grid[x][y] == -1)
return 0;//其中的-1表示是原矩阵的-1
if (grid[x][y] == 2) {
//这一句很关键,paths表示当前剩下的路径的长度,其为0表示已经走完了,开始收集,return 1 在原来的res基础上加上这个方案
//当然有场景是未走完全部的0后,到达2这个终点的,这时候并不开始计算路径,因为paths不是0,表示没有全部走完0这种点,return 0 加上后对结果影响
return counts == 0 ? 1 : 0;
}
grid[x][y] = -1;//如果当前的位置未被走过,标记为-1表示已经走过
int res = 0;
for (auto & direction : directions) {//四个方向的结果都走,res+注意
res += dfs(x + direction[0], y + direction[1], counts - 1, grid);
}
grid[x][y] = 0;//恢复当前的位置表示可走
return res;
}
public:
int uniquePathsIII(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[0].size();
int X = 0, Y = 0, counts = 1; //开始时的坐标轴(X,Y)及路径长度(初始化时为1,因为1本身也可以走)
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if(grid[i][j] == 1){
X = i;
Y = j;
}else if(grid[i][j] == 0){
counts++;
}
}
}
return dfs(X, Y, counts, grid);
}
};