[Leetcode] 490. The Maze 解题报告

  • Post author:
  • Post category:其他

题目

There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolling updownleft or right, but it won’t stop rolling until hitting a wall. When the ball stops, it could choose the next direction.

Given the ball’s start position, the destination and the maze, determine whether the ball could stop at the destination.

The maze is represented by a binary 2D array. 1 means the wall and 0 means the empty space. You may assume that the borders of the maze are all walls. The start and destination coordinates are represented by row and column indexes.

Example 1

Input 1: a maze represented by a 2D array

0 0 1 0 0
0 0 0 0 0
0 0 0 1 0
1 1 0 1 1
0 0 0 0 0

Input 2: start coordinate (rowStart, colStart) = (0, 4)
Input 3: destination coordinate (rowDest, colDest) = (4, 4)

Output: true
Explanation: One possible way is : left -> down -> left -> down -> right -> down -> right.

Example 2

Input 1: a maze represented by a 2D array

0 0 1 0 0
0 0 0 0 0
0 0 0 1 0
1 1 0 1 1
0 0 0 0 0

Input 2: start coordinate (rowStart, colStart) = (0, 4)
Input 3: destination coordinate (rowDest, colDest) = (3, 2)

Output: false
Explanation: There is no way for the ball to stop at the destination.

Note:

  1. There is only one ball and one destination in the maze.
  2. Both the ball and the destination exist on an empty space, and they will not be at the same position initially.
  3. The given maze does not contain border (like the red rectangle in the example pictures), but you could assume the border of the maze are all walls.
  4. The maze contains at least 2 empty spaces, and both the width and height of the maze won’t exceed 100.

思路

我开始把题目的意思给理解错了:必须是球能够停下来的地方才算是能够到达。如果球仅仅经过该格子,但是停不下来,那么就不算能够到达。这道题目用DFS或者BFS都可以解决,也算是DFS和BFS的一个小变种而已。由于能够停下来的位置及其有限,所以我们改用set来记录已经访问过的格子(当然用二维数组记录也是可以的)。此外,我们设计一个go2End函数,来计算球朝某个方向滚动时的下一个停靠点。下面就看看DFS和BFS分别怎么来做了。

1、DFS:对于DFS而言,我们首先判断是否已经到达了destination,如果是则直接返回;否则就看该位置是否已经被访问过了,如果是则返回,否则就记当前位置已经被访问(如果没有这一步,将会导致DFS无法结束)。然后就分别用DFS尝试四个不同方向,有任何一个方向可以到达destination就直接返回true。

2、BFS:对于BFS而言,思路类似。我们首先建立一个队列,并且将start压入队列。每次从队列头部拿出当前位置。如果该位置是destination则直接返回,否则就看该位置是否还没有被访问,如果没有被访问,就置为已访问,并将其四个方向上移动可以停靠的点加入队列。如果队列都空了还没有发现可以到达的路径,那么就说明无法到达了。

代码

1、DFS:

class Solution {
public:
    bool hasPath(vector<vector<int>>& maze, vector<int>& start, vector<int>& destination) {
        set<vector<int>> visited;
        return DFS(maze, start, destination, visited);
    }
private:
    bool DFS(vector<vector<int>> &maze, vector<int> &start, vector<int> &destination, set<vector<int>> &visited) {
        if(start == destination) {
            return true;
        }
        if(visited.find(start) != visited.end()) {      // already visited
            return false;
        }
        visited.insert(start);
        vector<vector<int>> dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
        for(int i = 0; i < 4; ++i) {
            vector<int> res = go2End(maze, start, dirs[i]);
            if(res == destination || DFS(maze, res, destination, visited)) {
                return true;
            }
        }
        return false;
    }
    vector<int> go2End(vector<vector<int>> &maze, vector<int> start, vector<int> &dir) {
        vector<int> new_start = {start[0] + dir[0], start[1] + dir[1]};
        int row_num = maze.size(), col_num = maze[0].size();
        if(new_start[0] < 0 || new_start[0] >= row_num || new_start[1] < 0 || new_start[1] >= col_num ||
           maze[new_start[0]][new_start[1]] == 1) {
            return start;
        }
        return go2End(maze, new_start, dir);
    }
};

2:BFS:

class Solution {
public:
    bool hasPath(vector<vector<int>>& maze, vector<int>& start, vector<int>& destination) {
        set<vector<int>> visited;
        queue<vector<int>> q;
        q.push(start);
        vector<vector<int>> dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
        while (!q.empty()) {
            vector<int> pos = q.front();
            q.pop();
            if (pos == destination) {
                return true;
            }
            if (visited.find(pos) == visited.end()) {   // not visited yet
                visited.insert(pos);
                for(int i = 0; i < 4; ++i) {
                    vector<int> res = go2End(maze, pos, dirs[i]);
                    q.push(res);
                }
            }
        }
        return false;
    }
private:
    vector<int> go2End(vector<vector<int>> &maze, vector<int> start, vector<int> &dir) {
        vector<int> new_start = {start[0] + dir[0], start[1] + dir[1]};
        int row_num = maze.size(), col_num = maze[0].size();
        if(new_start[0] < 0 || new_start[0] >= row_num || new_start[1] < 0 || new_start[1] >= col_num ||
           maze[new_start[0]][new_start[1]] == 1) {
            return start;
        }
        return go2End(maze, new_start, dir);
    }
};


版权声明:本文为magicbean2原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。