扫雷(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); }