暴力宽搜。
题目中告诉我们一共有两个状态,临海土地被淹没前,临海土地被淹没后。
两层循环地图,发现一个 ‘#’ 后就入队 ,进行 bfs。然后演化,将那一整个连通的 ‘#’ 都搜索一遍。对于每个 ‘#’ ,检查它周围四个方向是海水还是土地,如果是土地,就把新的土地入队(每次入队之后都要把该位置标记,避免重复入队);如果是海水那么 就设置一个变量 cnt2 ,令 cnt2++(通过一个 flag 来标记,一个 ‘#’ 只用统计一次)。
在一次 bfs 中,用 cnt 统计 ‘#’ 的数量。
将一个连通的 ‘#’ 小岛遍历完后比较 cnt 和 cnt2 的数量。cnt 是这个小岛上的土地数量,cnt2 是这个小岛上将要被淹没(濒临海水)的土地数量。如果 cnt 等于 cnt2 意味着这个小岛全军覆没,ans++ 。
划重点:对于一个小岛,在探寻某 ‘#’ 四周土地的时候,判断当前位置是否会被淹没,统计一个小岛总共有多少块土地 cnt ,和被淹没的土地数 cnt2,来判断当前小岛会不会被淹!
#include<bits/stdc++.h>
using namespace std;
int n,ans=0;
char data[1005][1005];
int mark[1005][1005]={0};
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};struct point{
int x,y;
};
void dfs(int i,int j){
int cnt = 0;
int cnt2 = 0;
queue<point>q;
point t;
t.x = i;
t.y = j;
q.push(t);
mark[i][j] = 1;
while(!q.empty()){
cnt++;//当前海岛拥有 土地数 加一
point f;
f = q.front();
q.pop();
int k;
int x,y;
bool flag = false;
for(k = 0;k<=3;k++){
x = f.x + dx[k];// 考虑:这里的数组不会越界对吧?
y = f.y + dy[k];
if(data[x][y]=='.') flag = true;// 如果周边有海,那么标记这块土地会被淹
if(data[x][y]=='#' && !mark[x][y]){
mark[x][y] = 1;
point w;
w.x = x;
w.y = y;
q.push(w);
}
}
if(flag) cnt2++;//会被淹的土地加一
}
if(cnt==cnt2) ans++;// 如果这个岛拥有的所有土地和 要被淹的土地数量一样多
// 说明整个岛都被淹了
}
int main(){
cin>>n;
int i,j;
for(i=0;i<n;i++){
for(j=0;j<n;j++){
cin>>data[i][j];
}
}
for(i=1;i<n-1;i++){
for(j=1;j<n-1;j++){
if(data[i][j]=='#' && !mark[i][j]) dfs(i,j);
}
}
cout<<ans<<endl;
return 0;
}