题解:P16486 [GKS 2014 #C] Minesweeper
caozexuan101 · · 题解
题解:P16486 [GKS 2014 #C] Minesweeper
解题思路
依旧数据很少,可以用深搜,先预处理格子周围的地雷数量,再寻找不是地雷的格子开始深搜(深搜过程其实类似连通块问题),每深搜一次步数加一,最终按格式(空格加了吗)输出即可。
注意
多测需清空。
正确代码
#include<bits/stdc++.h>
using namespace std;
int n;
char mp[305][305];//地图
int dl[305][305];// 格子周围的地雷数量
bool vis[305][305];//判断是否走过
int dx[8]={1, 1, 0, -1, -1, -1, 0, 1};
int dy[8]={0, 1, 1, 1, 0, -1, -1, -1};
bool ok(int x,int y){
return x>=0&&x<n&&y>=0&&y<n;
}//判断是否在网格内
void dlsl(){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(mp[i][j]=='*'){
dl[i][j]=-1;//标记地雷
continue;
}
int cnt=0;
for(int k=0;k<8;k++){
int nx=i+dx[k];
int ny=j+dy[k];
if(ok(nx,ny)&&mp[nx][ny]=='*'){
cnt++;
}
}
dl[i][j]=cnt;
}
}
}
void dfs(int x,int y){
vis[x][y]=true;
if(dl[x][y]>0)return;
for(int k=0;k<8;k++){
int nx=x+dx[k];
int ny=y+dy[k];
if(ok(nx,ny)&&!vis[nx][ny]&&mp[nx][ny]!='*'){
vis[nx][ny]=true;
if(!dl[nx][ny]){
dfs(nx,ny);
}
}
}
}
int main() {
int t;
cin>>t;
for(int tt=1;tt<=t;tt++){
cin>>n;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>mp[i][j];
}
}
memset(vis,0,sizeof(vis));//多测需清空
dlsl();
int step=0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(mp[i][j]!='*'&&!vis[i][j]&&dl[i][j]==0){
step++;
dfs(i,j);
}
}
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(mp[i][j]!='*'&&!vis[i][j]){
step++;
vis[i][j]=true;
}
}
}
cout<<"Case #"<<tt<<": "<<step<<endl;//空格没打硬控15分钟
}
return 0;
}