leetcode 529.扫雷游戏(DFS)

leetcode 529.扫雷游戏(DFS)

题目描述

在这里插入图片描述

样例描述

在这里插入图片描述

算法分析

这个题还是规矩比较多的,尤其是一开始打算用C语言做(本人学习密码编码学,算法工程上都是用C实现,所以刻意练习用C写算法)。一看到那个C语言提交的模板就傻了,那参数多的啊……果断C++写!

好了,废话不多说!

提炼题目描述

给出click的位置,要求问你click之后的游戏面板会变成啥子模样~
如果你不小心点到了雷,那就显示一个 ‘X’ ,游戏自然结束(和扫雷一样~)
否则就需要去处理很多东西了,你想想看,自己玩扫雷的时候,是不是一点就空出来一大片,这就是根据这个算法去处理的。处理的规则是什么呢??

规则1 :

如果你点到的周围有雷,那么就不继续了,只留下八个方向上雷的个数,告诉玩家。

规则2:

如果你点到的八个方向上一个雷也没有,那就由 ‘E’ 变成 ‘B’ 。相当于告诉玩家,你点过了,这也是为何你扫雷游戏有时候一点空出一大片的原因。就是因为这个位置周围没有雷,所以直接显示成 ‘E’ !!

编码实现

好了,规则其实也就这么两点啦,是自己太浮躁一开始没看进去啦~

然后如何编码实现呢?给出一个click的点,然后你可以得到click的行 r 和 列 c,如果这个位置就是雷,那么直接表示成 ‘X’ ,本次 click 结束!否则进入dfs()!

具体怎么去 dfs 呢?首先初始化的面板只有 ‘M’ 和 ‘E’ ,所以能够进入 dfs() 就说明你当前是 ‘E’,所以需要先判断它周围有无雷,有的话,求出有多少,然后此处的位置改成数字即可!改成数字之后这个位置也不需要继续下去了~否则就说明这个位置周围没有雷,就改成 ‘B’,代表是个周围没有雷的,且已经点击过的地方!!然后朝着八个方向去递归,而递归的出口如何处置呢?我们可以设置一个状态记录的数组,如果当前的点是已经处理过的,那就return,就好了!

具体解题代码

class Solution {
    
    
public:
    int dir[8][2] = {
    
    {
    
    0, 1}, {
    
    0, -1}, {
    
    1, 0}, {
    
    -1, 0}, {
    
    1, 1}, {
    
    1, -1}, {
    
    -1, 1}, {
    
    -1, -1}};
    int vis[50][50] = {
    
    0};
    void dfs(int x, int y, vector<vector<char>>& board){
    
    
        if(vis[x][y])
            return ;
        vis[x][y] = 1;
        int cnt = 0;
        for(int i = 0;i < 8;++i){
    
    
            int dx = x + dir[i][0];
            int dy = y + dir[i][1];
            if(dx >= 0 && dx < (int)board.size() && dy >= 0 && dy < (int)board[0].size()){
    
    
                if('M' == board[dx][dy])
                    cnt++;
            }
        }
        if(cnt > 0){
    
    
            board[x][y] = cnt + '0';
        }
        else{
    
    
            board[x][y] = 'B';
            for(int i = 0;i < 8;++i){
    
    
                int dx = x + dir[i][0];
                int dy = y + dir[i][1];
                if(dx >= 0 && dx < (int)board.size() && dy >= 0 && dy < (int)board[0].size())
                    if(!vis[dx][dy])
                        dfs(dx, dy, board);
            }
        }
    }

    vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {
    
    
        int r = click[0], c = click[1];
        if('M' == board[r][c])
            board[r][c] = 'X';
        else
            dfs(r, c, board);
        return board;
    }

};

提交的结果

在这里插入图片描述
这个性能很不理想啊,希望有提出更好的解决方案的同仁前辈,不吝赐教!

解答一个问题

有很多人会问,为何样例的正上方还有一个 ‘E’ 没有被处理呢??
其实很简单,因为从click的位置出发,在遇到这个 ‘E’ 之前,会遇到周围有雷的位置,遇到这些位置的时候,就会停止递归处理了!所以无法处理这个 ‘E’ ~
其实你去玩扫雷这个游戏,也会发现,人家也就是这么处理的!

写在后面

由于本人能力有限,如果有写错或者有瑕疵的地方,还请各位不吝赐教!希望能够通过留言私信,得到您的指教!

猜你喜欢

转载自blog.csdn.net/qq_44274276/article/details/108134879