18清明校内测试T3

扫雷(mine)

Time Limit:1000ms   Memory Limit:128MB

 

题目描述

rsy最近沉迷于一款叫扫雷的游戏。

这个游戏是这样的。一开始网格上有n*m个位置,其中有一些位置有雷。每次rsy可以左键点击一个方块,此时若这个方块是雷,则rsy被炸,游戏结束,否则如果这个位置周围8格有x个雷,则会显示数字x。特别地,当x=0时,系统会自动左键点击附近8个位置。(此时附近8个位置一定没有雷,假如附近8个位置仍存在x=0,则继续往外扩展)想要更进一步获得关于题目的信息,打开程序->附近->游戏->扫雷或者直接打开下发的可执行文件。

或者rsy右键点击一个位置,标注这个位置是雷。

不幸的是,她鼠标不能左右键同时点击,因此只需考虑她左键点击与右键点击就可以了。

注意游戏胜利的条件是所有非雷的位置都被左键点击到。(特别地,当一开始时n*m个位置都是雷时,LYK自动获得胜利)

rsy从网上下载了金手指,很轻易地就掌握了所有雷所在的位置。rsy想通过最少的点击次数获得胜利(这里的点击次数不包括系统自动点击)。于是他来请求你的帮助。

 

输入格式(mine.in)

    第一行两个数n,m。

    接下来n行,每行m个数ai,j,表示这个矩阵。若ai,j=’*’则表示这个位置是雷,若ai,j=’.’则表示不是雷。

 

输出格式(mine.out)

一个数表示答案。

 

输入样例

3 3

..*

...

..*

 

输出样例

2

 

对于30%的数据n=1;

对于另外20%的数据n,m<=3;

对于再另外20%的数据*大致占矩阵的2/3且数据随机。

对于100%的数据n,m<=1000。

 

 

Hint:

适度游戏益脑,沉迷游戏伤身。


 

因为数据范围并不是很大,所以带优化的搜索应该能过。

于是乎开始敲代码。

但是写着写着发现一个问题,如果一个非雷的点的八个方向上有雷,但是通过鼠标右键将它标记之后,如果在点这个非雷的点,是否会出现系统自动点击周围的点。我在这里纠结了很长时间,到最后让老师用std跑了一组数据就知道根本不用考虑这么多。

就是下面这组

 

3 3
...
..*
...

 

至于为什么自己想吧。

下面来看看正解。没错就是搜索。

 


 

我们来设计一下BFS做这道题,首先应该把每个点周围的雷的数量存在一个数组中去,然后每一个点都判断一下,如果这个点周围没有雷,并且这里不是雷而且没有被访问过,那就可以就从这里向外扩展,不过要记得在BFS之前就将要进行扩展的点标记为访问。就可以了。

扩展的时候把这个这个点周围的点全部标记,如果被标记的点内存在周围没有雷的点,就把这个点扔到队列里去。继续扩展

整张地图全扩展完了之后,还要判断一下有没有落单的点,有的话,就ans++

代码

 

#include <iostream>
#include <cstdio>
#include <queue>

using namespace std;

int n, m, ans;
char map[1005][1005];
int dx[10] = {1, -1, 0, 0, 1, -1, 1, -1};
int dy[10] = {0, 0, 1, -1, -1, 1, 1, -1};
struct node {
    int x, y;
};
bool vis[1005][1050];
int num[1005][1005];
queue<node> P;

void bfs(node now) {
    while(!P.empty()) {
        now = P.front();
        P.pop();
        int x = now.x, y = now.y;
        for(int k=0; k<8; k++) {
            int xx = dx[k]+x, yy = dy[k]+y;
            if(xx <= n&&xx > 0&&yy <= m&&yy > 0&&map[xx][yy] == '.'&&vis[xx][yy] == 0) {
                vis[xx][yy] = 1;
                if(num[xx][yy] == 0) {
                    P.push((node) {xx, yy});
                }
            }
        }
    }
}

int main() {
    scanf("%d%d", &n, &m);
    for(int i=1; i<=n; i++) {
        scanf("%s", map[i]+1);
    }
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=m; j++) {
            if(map[i][j] == '.') {
                for(int k=0; k<8; k++) {
                    if(map[i+dx[k]][j+dy[k]] == '*') {
                        num[i][j]++;
                    }
                }
            }
            else {
                num[i][j] = 1;
            }
        }
    }
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=m; j++) {
            if(vis[i][j] == 0&&num[i][j] == 0) {
                P.push((node) {i, j});
                vis[i][j] = 1;
                bfs(P.front());
                ans++;
            }
        }
    }
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=m; j++) {
            if(vis[i][j] == 0&&map[i][j] != '*')
                ans++;
        }
    }
    printf("%d", ans);
}

 

posted @ 2018-04-08 10:05  Mystical-W  阅读(159)  评论(0编辑  收藏  举报