dfs学习之扫雷问题

来源:互联网 发布:好易网络电视apk 编辑:程序博客网 时间:2024/06/05 05:21

LeetCode题目529 之 Minesweeper


题目描述:

Let’s play the minesweeper game (Wikipedia online game)!

You are given a 2D char matrix representing the game board. ‘M’ represents an unrevealed mine, ‘E’ represents an unrevealed empty square, ‘B’ represents a revealed blank square that has no adjacent (above, below, left, right, and all 4 diagonals) mines, digit (‘1’ to ‘8’) represents how many mines are adjacent to this revealed square, and finally ‘X’ represents a revealed mine.

Now given the next click position (row and column indices) among all the unrevealed squares (‘M’ or ‘E’), return the board after revealing this position according to the following rules:

If a mine (‘M’) is revealed, then the game is over - change it to ‘X’.
If an empty square (‘E’) with no adjacent mines is revealed, then change it to revealed blank (‘B’) and all of its adjacent unrevealed squares should be revealed recursively.
If an empty square (‘E’) with at least one adjacent mine is revealed, then change it to a digit (‘1’ to ‘8’) representing the number of adjacent mines.
Return the board when no more squares will be revealed.
Example 1:

Input:

[['E', 'E', 'E', 'E', 'E'], ['E', 'E', 'M', 'E', 'E'], ['E', 'E', 'E', 'E', 'E'], ['E', 'E', 'E', 'E', 'E']]

Click : [3,0]

Output:

[['B', '1', 'E', '1', 'B'], ['B', '1', 'M', '1', 'B'], ['B', '1', '1', '1', 'B'], ['B', 'B', 'B', 'B', 'B']]

Example 2:

Input:

[['B', '1', 'E', '1', 'B'], ['B', '1', 'M', '1', 'B'], ['B', '1', '1', '1', 'B'], ['B', 'B', 'B', 'B', 'B']]

Click : [1,2]

Output:

[['B', '1', 'E', '1', 'B'], ['B', '1', 'X', '1', 'B'], ['B', '1', '1', '1', 'B'], ['B', 'B', 'B', 'B', 'B']]

Note:

The range of the input matrix’s height and width is [1,50].
The click position will only be an unrevealed square (‘M’ or ‘E’), which also means the input board contains at least one clickable square.
The input board won’t be a stage when game is over (some mines have been revealed).
For simplicity, not mentioned rules should be ignored in this problem. For example, you don’t need to reveal all the unrevealed mines when the game is over, consider any cases that you will win the game or flag any squares.

分析

这道题的做法是用dfs来完成。从题目描述来讲,点击某个位置有三种可能,一是很遗憾,你触碰的这个位置,游戏结束,结果就将该点值M换成X,返回原来的矩阵。二是你触碰的这个位置是安全值,并且在方圆为1的范围内的地雷数>=1,则返回将原来的值替换成地雷数n,返回该矩阵。三就是需要递归的情况。假如该点的地雷数是0,显然周围都没有地雷,所以游戏自动地把附近的八个点都帮你点击了,类似地,游戏自动点击的同时如果再遇上该点的附近地雷数是0,继续点击下去。在这个思路下,有两种方法,一种是dfs,即一遇到地雷数为0时理科点击其附近的点,直到周围8个都完成任务后再回溯到上一层,当然这个时候要注意重复问题,作特定的标志即可。另外一种是bfs,即点击的时候遇到零值先记录下来,等到周围八个都点击完了再确定谁需要继续点击下去。我用的是前者,后者bfs没实验过不知到能不能行得通,应该是可以的。欢迎评论指教!

代码

class Solution {public:    int findNum(vector<vector<char> > board, int x, int y) {        int pos[8][2] = {{-1,-1}, {-1,0}, {-1,1}, {0,-1}, {0,1}, {1,-1}, {1,0}, {1,1}};        int num = 0;        for (int i = 0; i < 8; i++) {            int px = x+pos[i][0];            int py = y+pos[i][1];            if (px < 0 || px >= board.size()) continue;            if (py < 0 || py >= board[0].size()) continue;            if (board[px][py] == 'M') num++;        }        return num;    }    vector<vector<char> > updateBoard(vector<vector<char> >& board, vector<int>& click) {        vector<vector<char> > result;        if (board.size() <= 0) return result;        if (board.size() <= 0) return result;        if (click.size() <= 0) return result;        int x = click[0];        int y = click[1];        int x_size = board.size();        int y_size = board[0].size();        if (x >= x_size) return result;        if (y >= y_size) return result;        if (board[x][y] == 'M') {            board[x][y] = 'X';            return board;        }        int num = findNum(board, x, y);        if (num != 0) {            board[x][y] = '0'+num;            return board;        }        board[x][y] = 'B';        int pos[8][2] = {{-1,-1}, {-1,0}, {-1,1}, {0,-1}, {0,1}, {1,-1}, {1,0}, {1,1}};        for (int i = 0; i < 8; i++) {            int px = x+pos[i][0];            int py = y+pos[i][1];            if (px < 0 || px >= board.size()) continue;            if (py < 0 || py >= board[0].size()) continue;            if (board[px][py] != 'E') continue;            vector<int> click1;            click1.push_back(px);            click1.push_back(py);            board = updateBoard(board, click1);        }        return board;    }};
原创粉丝点击