leetcode 529 扫雷游戏
一、题目描述
二、解题思路
整体思路
可以采用深度优先搜索+剪枝的方法来解决这个问题,这个问题其实是floodfill算法(连通块)的一类典型问题。
具体思路
(1)main函数:
<1>如果board[click[0]][click[1]]=='M',也就是第一次点击就遇到地雷了,就将该位置修改为'X',然后返回盘面board;
<2>否则,就以点击的位置为起点,调用dfs函数,最后返回修改完成的盘面board即可;
(2)全局变量:
<1>m,n分别表示盘面board的行数和列数;
<2>visited数组用于标记(i,j)位置是否被访问,如被访问则visited[i][j]=true,否则visited[i][j]=false;
(3)函数功能:dfs函数完成从(i,j)位置为起点进行扫雷游戏,修改盘面直至达到所需的状态;
(4)函数体:
<1>首先,将visited[i][j]修改为true;
<2>接下来,对(i,j)位置进行上、下、左、右、左上、左下、右上、右下扫描,have用于记录周围是否有地雷。
1)如果遍历完成无地雷(have==false),就将board[i][j]修改为'B';
2)如果有地雷(have==true),就将board[i][j],修改为地雷的数量(字符),无需再向下探索,直接return;
<3>如果have==false,就是周围无地雷,则按照上、下、左、右、左上、左下、右上、右下全进行方位探索,如果(x,y)未越界且未被访问就对(x,y)递归调用dfs函数;
三、代码实现
class Solution {int m,n;vector<vector<bool>> visited;
public:vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {m=board.size();n=board[0].size();visited.resize(m,vector(n,false));//特殊情况处理if(board[click[0]][click[1]]=='M'){board[click[0]][click[1]]='X';return board;}dfs(board,click[0],click[1]);return board;}int dx[8]={0,1,0,-1,1,1,-1,-1};int dy[8]={1,0,-1,0,1,-1,-1,1};void dfs(vector<vector<char>>& board,int i,int j){visited[i][j]=true;//查看(i,j)块周围有没有地雷bool have=false;int count=0;for(int k=0;k!=8;k++){int x=i+dx[k];int y=j+dy[k];if(x>=0&&x<m&&y>=0&&y<n&&board[x][y]=='M'){have=true;count++;}}//如果周围有地雷则无需再递归if(have){board[i][j]='0'+count;return;}if(!have&&board[i][j]=='E') board[i][j]='B';for(int k=0;k!=8;k++){int x=i+dx[k];int y=j+dy[k];if(x>=0&&x<m&&y>=0&&y<n&&!visited[x][y])dfs(board,x,y);}}
};