题目

在二维网格 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

解答

答案所要求的路径其实就是从1到2在没有经过重复的位置的情况下长度为
【0的个数 + 2】的路径 所以其实可以直接dfs,并在dfs时记录路径的长度,当我们走到2的位置的时候,检查路径长度是否足够长即可。为了避免走重复的位置,我们在经过一个位置时将该位置标记为-1,递归函数结束时恢复为0即可。

class Solution {
public:
    int uniquePathsIII(vector<vector<int>>& grid) {
        int m = grid.size(), n = grid[0].size();
        // 定义四个方向的偏移量,用于遍历上、下、左、右四个方向
        short dis_x[] = {1, -1, 0, 0}, dis_y[] = {0, 0, 1, -1};
        int ret = 0;
        // x1, y1是起点(值为1)的坐标,x2, y2是终点(值为2)的坐标,len是目标长度(包括起点和终点)
        int x1, y1, x2, y2, len = 2;
        // 遍历整个矩阵,计算0的个数,以及获取1和2的坐标
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                switch (grid[i][j]) {
                    case 0: // 值为0,代表可访问的空格,目标长度len需要加1
                        ++len;
                        break;
                    case 1: // 值为1,代表起点
                        x1 = i;
                        y1 = j;
                        break;
                    case 2: // 值为2,代表终点
                        x2 = i;
                        y2 = j;
                        break;
                }
            }
        }
        
        // 定义深度优先搜索函数,使用lambda表达式
        function<void(int, int, int)> dfs = [&](int x, int y, int cnt) {
            if (x == x2 && y == y2) { // 如果当前坐标为终点坐标
                if (cnt == len) // 如果路径长度等于目标长度(包括起点和终点),则结果ret加1
                    ++ret;
                return;
            }
            grid[x][y] = -1; // 将当前坐标标记为已访问(-1)
            for (int i = 0; i < 4; ++i) { // 尝试向四个方向进行搜索
                int nx = dis_x[i] + x; // 计算下一个搜索位置的横坐标
                int ny = dis_y[i] + y; // 计算下一个搜索位置的纵坐标
                // 检查下一个搜索位置是否合法(在矩阵范围内且不为已访问的位置)
                if (nx >= 0 && ny >= 0 && nx < m && ny < n && grid[nx][ny] != -1) {
                    dfs(nx, ny, cnt + 1); // 继续向下一个位置进行搜索,路径长度加1
                }
            }
            grid[x][y] = 0; // 恢复当前坐标的值为0,表示当前位置未被访问
        };
        
        dfs(x1, y1, 1); // 调用深度优先搜索函数,初始长度为1(起点)
        return ret; // 返回结果
    }
};

作者:吸鼠霸王
链接:https://leetcode.cn/problems/unique-paths-iii/solutions/2212729/dfs-hui-su-by-v-me-50-l178/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。