题意
给定一个n*m的地图 0是水 1是陆地 统计一共有多少个岛
如果一个岛被另一个岛环住 就不统计入内 这个意思 看样例图比较好理解
思路
地图外的都是外海 可能会跟地图内的内海联通 那么把这些联通的内海都标记为外海
只有与外海相连的岛屿才需要统计
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int,int>
#define ar2 array<int,2>
#define ar3 array<int,3>
#define ar4 array<int,4>
#define endl '\n'
void cmax(int &a,int b){a=max(a,b);}
void cmin(int &a,int b){a=min(a,b);}
const int N=100,MOD=1e9+7,INF=0x3f3f3f3f,LINF=LLONG_MAX;
char g[N][N];
bool st[N][N];
int n,m;
void dfs_sea(int x,int y){
int dx[8]={-1,-1,1,0,0,1,1,1};
int dy[8]={-1,0,1,-1,1,-1,0,1};
for(int i=0;i<8;i++){
int tx=x+dx[i],ty=y+dy[i];
if(tx<0||tx>n+1||ty<0||ty>m+1||g[tx][ty]=='1'||st[tx][ty]) continue;
if(g[tx][ty]=='0') {
g[tx][ty]='2';
}
st[tx][ty]=1;
dfs_sea(tx,ty);
}
}
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
bool check(int x,int y){
for(int i=0;i<4;i++){
int tx=x+dx[i],ty=y+dy[i];
if(g[tx][ty]=='2') return 1;
}
return 0;
}
void dfs(int x,int y){
for(int i=0;i<4;i++){
int tx=x+dx[i],ty=y+dy[i];
if(st[tx][ty]) continue;
if(g[tx][ty]=='1'){
st[tx][ty]=1;
dfs(tx,ty);
}
}
}
void solve() {
cin>>n>>m;
memset(st,0,sizeof(st));
for(int i=0;i<=n+1;i++){
for(int j=0;j<=m+1;j++){
g[i][j]='2';
}
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++){
cin>>g[i][j];
}
}
dfs_sea(0,0);
int cnt=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(g[i][j]=='1'&&check(i,j)&&st[i][j]==0){
st[i][j]=1;
dfs(i,j);
cnt++;
}
}
}
cout<<cnt<<endl;
// for(int i=0;i<=n+1;i++){
// for(int j=0;j<=m+1;j++) cout<<g[i][j];
// cout<<endl;
// }
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t=1;
cin>>t;
while (t--) solve();
}
细节
我一开始把八联通的方向数组写错了 写成了
int dx[]={0,0,0,-1,-1,1,1,1};
int dy[]={0,1,-1,0,1,0,1,-1};
实际上应该两个0 三个1和-1
int dx[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
int dy[8] = {-1, 0, 1, -1, 1, -1, 0, 1};
另外记得在这段代码中
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(g[i][j]=='1'&&check(i,j)&&st[i][j]==0){
st[i][j]=1;
dfs(i,j);
cnt++;
}
}
}
if判断条件中要加上st[i][j]==0 不然会重复计算很多个岛屿
在if里面要记得把st[i][j]标记为1 不然这个起点会被重复走
这两个我一开始都忘记了 导致我调了好久
hhh好一段时间没写dfs了