529. Minesweeper

▶ 扫雷的扩展判定。已知棋盘上所有点的情况(雷区 'M',已翻开空白区 'B',未翻开空白区 'E',数字区 '1' ~ '8'),现在给定一个点击位置(一定在空白区域),若命中雷区则将被命中的 M 改为 X,若命中空白区则将点击位置扩展为带有数字边界的安全区。

● 自己的解法,28 ms,深度优先遍历。改善了边界判定的方法,以后写类似的矩阵函数的时候可以借鉴。实际上可以在 extend 开头判定 click 是否在棋盘范围内,以后就可以强行 8 个方向搜索(见后面大佬的代码)

 1 class Solution
 2 {
 3 public:
 4     vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click)
 5     {
 6         if (board[click[0]][click[1]] == 'M')
 7         {
 8             board[click[0]][click[1]] = 'X';
 9             return board;
10         }
11         extend(board, click);
12         return board;
13     }
14     void extend(vector<vector<char>>& board, vector<int>& click)
15     {
16         const int row = board.size(), col = board[0].size(), rowClick = click[0], colClick = click[1];        
17         char location = ~0;
18         int count = 0;
19         vector<int> tempClick;
20         // 计算当前位置的相邻情况,location从左边起 8 位分别表示 右,右上,上,左上,左,左下,下,右下 是否有相邻块
21         if (colClick % col == col - 1)  // 右,11000001
22             location &= ~193;
23         if (rowClick == 0)              // 上,01110000
24             location &= ~112;    
25         if (colClick % col == 0)        // 左,00011100
26             location &= ~28;
27         if (rowClick == row - 1)        // 下,00000111
28             location &= ~7;
29         // 统计周围雷数计数,从右开始,逆时针方向搜索
30         if (location & 1 << 7 && board[rowClick][colClick + 1] == 'M')
31             count++;
32         if (location & 1 << 6 && board[rowClick - 1][colClick + 1] == 'M')
33             count++;
34         if (location & 1 << 5 && board[rowClick - 1][colClick] == 'M')
35             count++;
36         if (location & 1 << 4 && board[rowClick - 1][colClick - 1] == 'M')
37             count++;
38         if (location & 1 << 3 && board[rowClick][colClick - 1] == 'M')
39             count++;
40         if (location & 1 << 2 && board[rowClick + 1][colClick - 1] == 'M')
41             count++;
42         if (location & 1 << 1 && board[rowClick + 1][colClick] == 'M')
43             count++;
44         if (location & 1 << 0 && board[rowClick + 1][colClick + 1] == 'M')
45             count++;        
46         if (count)// 周围有雷,本地为数字,停止搜索
47         {
48             board[rowClick][colClick] = count + '0';
49             return;
50         }        
51         board[rowClick][colClick] = 'B';// 周围无雷,本地为安全区,继续搜索
52         if (location & 1 << 7 && board[rowClick][colClick + 1] == 'E')
53             extend(board, tempClick = { rowClick, colClick + 1 }); 
54         if (location & 1 << 6 && board[rowClick - 1][colClick + 1] == 'E')
55             extend(board, tempClick = { rowClick - 1, colClick + 1 });
56         if (location & 1 << 5 && board[rowClick - 1][colClick] == 'E')
57             extend(board, tempClick = { rowClick - 1, colClick });
58         if (location & 1 << 4 && board[rowClick - 1][colClick - 1] == 'E')
59             extend(board, tempClick = { rowClick - 1, colClick - 1 });
60         if (location & 1 << 3 && board[rowClick][colClick - 1] == 'E')
61             extend(board, tempClick = { rowClick, colClick - 1 });
62         if (location & 1 << 2 && board[rowClick + 1][colClick - 1] == 'E')
63             extend(board, tempClick = { rowClick + 1, colClick - 1 });
64         if (location & 1 << 1 && board[rowClick + 1][colClick] == 'E')
65             extend(board, tempClick = { rowClick + 1, colClick });
66         if (location & 1 << 0 && board[rowClick + 1][colClick + 1] == 'E')
67             extend(board, tempClick = { rowClick + 1, colClick + 1 });
68         return;
69     }
70 };

● 大佬的代码,38 ms,深度优先遍历,与后面的广度优先遍历在格式上保持一致

 1 class Solution
 2 {
 3 public:
 4     vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click)
 5     {
 6         int m = board.size(), n = board[0].size(), row = click[0], col = click[1];
 7         int count, i, j, r, c;
 8         vector<int>tempClick;
 9         if (board[row][col] == 'M')
10         {
11             board[row][col] = 'X';
12             return board;
13         }
14         for (count = 0, i = -1; i < 2; i++)
15         {
16             for (j = -1; j < 2; j++)
17             {
18                 if (i == 0 && j == 0)
19                     continue;
20                 r = row + i, c = col + j;
21                 if (r < 0 || r >= m || c < 0 || c < 0 || c >= n)
22                     continue;
23                 if (board[r][c] == 'M' || board[r][c] == 'X')
24                     count++;
25             }
26         }
27         if (count)
28         {
29             board[row][col] = (char)(count + '0');
30             return board;
31         }                
32         for (board[row][col] = 'B', i = -1; i < 2; i++)
33         {
34             for (j = -1; j < 2; j++)
35             {
36                 if (i == 0 && j == 0)
37                     continue;
38                 r = row + i, c = col + j;
39                 if (r < 0 || r >= m || c < 0 || c < 0 || c >= n)
40                     continue;
41                 if (board[r][c] == 'E')                 
42                     updateBoard(board, tempClick = { r, c });
43             }
44         }        
45         return board;
46     }
47 };

● 大佬的广度优先遍历,31 ms,最快的解法算法与之相同,但维护一个 unordered_set<int> 用于保存已经访问过的点来防止重复访问

 1 class Solution
 2 {
 3 public:
 4     vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click)
 5     {
 6         const int m = board.size(), n = board[0].size();
 7         queue<vector<int>> q;
 8         vector<int> cell;
 9         int row, col, count, i, j, r, c;
10         for (q.push(click); !q.empty();)
11         {
12             cell = q.front(),q.pop();
13             row = cell[0], col = cell[1];
14             if (board[row][col] == 'M')
15             {
16                 board[row][col] = 'X';
17                 continue;
18             }                                  
19             for (count = 0, i = -1; i < 2; i++)
20             {
21                 for (j = -1; j < 2; j++)
22                 {
23                     if (i == 0 && j == 0)
24                         continue;
25                     r = row + i, c = col + j;
26                     if (r < 0 || r >= m || c < 0 || c < 0 || c >= n)
27                         continue;
28                     if (board[r][c] == 'M' || board[r][c] == 'X')
29                         count++;
30                 }
31             }
32             if (count)
33             {
34                 board[row][col] = (char)(count + '0');
35                 continue;
36             }            
37             for (board[row][col] = 'B', i = -1; i < 2; i++)
38             {
39                 for (j = -1; j < 2; j++)
40                 {
41                     if (i == 0 && j == 0) 
42                         continue;
43                     r = row + i, c = col + j;
44                     if (r < 0 || r >= m || c < 0 || c < 0 || c >= n)
45                         continue;
46                     if (board[r][c] == 'E')
47                     {
48                         q.push(vector<int>{r, c});
49                         board[r][c] = 'B';
50                     }
51                 }
52             }
53         }
54         return board;
55     }
56 };
原文地址:https://www.cnblogs.com/cuancuancuanhao/p/8411107.html