先用dfs搜索出所有岛屿,并对每个岛屿进行编号。由于岛屿之间互相隔离,则如果岛屿的一个格子在一个环内,那么整个岛屿也都在环内。遍历所有的岛屿,选中当前岛屿的第一个格子,搜索周围海洋(当被一个环岛包围时,八个方向都不能穿过,反之则没有被环岛包围),若能搜索到地图的边界外,则此岛屿不在任何一个环内,则岛屿数+1,否则,该岛屿在某一个环岛内,则不需要加入该岛屿。
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
int n, m;
//存储每一个岛屿的第一个格子的基本信息
class Data{
public:
char number;//编号
int x, y;//坐标
Data(){}
Data(char nubmer, int x, int y){
this->number = number;
this->x = x;
this->y = y;
}
};
//方向数组
//上 下 左 右 左上 左下 右上 右下
int dx[] = {-1, 1, 0, 0, -1, 1, -1, 1};
int dy[] = {0, 0, -1, 1, -1, -1, 1, 1};
//dfs对岛屿进行编号
void dfs(vector<string>& graph, int i, int j, char number){
graph[i][j] = number;
//给岛屿编号,只需要 上下左右四个方向
for(int k = 0;k < 4;k++){
int x = i + dx[k];
int y = j + dy[k];
if(x>=0 && x<n && y>=0 && y<m && graph[x][y] == '1'){
dfs(graph, x, y, number);
}
}
}
//bfs判断该岛屿是否能到达外海(能到达则该岛屿没有被包围住)
bool bfs(vector<string> graph, int i, int j){
queue<pair<int, int>> que;
que.push({i, j});
while(!que.empty()){
//抵达外海需要8个方向
for(int k = 0;k < 8;k++){
int x = que.front().first + dx[k];
int y = que.front().second + dy[k];
//到外海了 => 越界
if(x<0 || x>=n || y<0 || y>=m) return true;
if(graph[x][y] == '0'){
graph[x][y] = '-1';
que.push({x, y});
}
}
que.pop();//出队
}
return false;//没有到外海
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while(T--){
cin >> n >> m;
int ans = 0;
vector<string> graph(n, "");//初始化
vector<Data> land;
for(int i = 0;i < n;i++){
cin >> graph[i];//输入图
}
//遍历图,给图编号
char number = '2';
for(int i = 0;i < n;i++){
for(int j = 0;j < m;j++){
if(graph[i][j] == '1'){
//传入第一个岛的信息
land.push_back(Data(number, i, j));
dfs(graph, i, j, number);
number++;
}
}
}
//遍历每个岛屿的第一个位置,如果该位置能到达最外海的位置,则该岛独立
for(auto it : land){
if(bfs(graph, it.x, it. y)) ans++;
}
cout << ans << endl;
//打印 被标号后的岛屿
// for(int i = 0;i < n;i++){
// for(int j = 0;j < m;j++){
// cout << graph[i][j] << " ";
// }
// cout << endl;
// }
}
return 0;
}
0 回复
0 转发
1 喜欢
4 阅读



