解题思路:
周围八格没有“空格”的“数字”个数求法:枚举所有雷,将雷旁边八连通格变为2,并把ans ++ ;(注意这个ans ++ 把坐标范围外的点也加进来了,所以在后续dfs中要减去)
"空"求法:枚举每个g[i][j] == 0的格子,dfs出它的最大空格,若遇到空格则继续枚举,若遇到数字则要将雷与空格中间的数字或者空与边界之间的数字则ans -- ;
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int N = 1010;
int ans;//记录最小点击数即可完成游戏的数目
int n, m;
int g[N][N];
bool st[N][N];//判断该空的八连通图是否被走过
int dx[8] = {-1, -1, -1, 0, 1, 1, 1, 0};//八连通图的八个方向
int dy[8] = {-1, 0, 1, 1, 1, 0, -1, -1};
void dfs(int x, int y)
{
st[x][y] = true;
for (int i = 0; i < 8; i ++ )//枚举8个方向
{
int a = x + dx[i], b = y + dy[i];
if (g[a][b] == -1) continue;//说明出界了
if (st[a][b]) continue;
if (g[a][b] != 0) //说明这是在雷与空之间的数字,或者空与边界之间的数字
{
ans -- ;
st[a][b] = true;
continue;
}
dfs(a, b);
}
}
int main()
{
cin >> n >> m;
memset(g, -1, sizeof g);//初始化防止越界
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
scanf("%d", &g[i][j]);
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
if (g[i][j] == 1)
{
for (int k = 0; k < 8; k ++ )
if (!g[i + dx[k]][j + dy[k]])//将雷旁边的八连通的图设为2
{
ans ++ ;
g[i + dx[k]][j + dy[k]] = 2;
}
}
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
if (!g[i][j] && !st[i][j])//找到与当前空相连的连通图
{
ans ++ ;
dfs(i, j);
}
cout << ans << endl;
return 0;
}