专栏文章

题解:P9243 [蓝桥杯 2023 省 B] 岛屿个数

P9243题解参与者 3已保存评论 3

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
3 条
当前快照
1 份
快照标识符
@mipo4xhm
此快照首次捕获于
2025/12/03 15:11
3 个月前
此快照最后确认于
2025/12/03 15:11
3 个月前
查看原文
这一题是数岛屿数量的进阶题目,难点在于如何判断该岛屿是否为子岛屿。我们可以将海域分为内海和外海,内海即由岛屿形成的环形区域内的海域。判断一个岛屿是否为子岛屿的关键在于其是否能到达外海。注意,在 dfs 染色时,我们从上下左右方向进行遍历,而在判断能否到达外海时,则需要从四面八方进行遍历。
贴上 AC 代码,(代码有注释) qwq
CPP
#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
using ll=long long;
char mp[60][60];
int vis[60][60]; // 经典 dfs 标记
int sc; // 染色编号
int v[60][60]; // 在查找该岛屿能否走到外海的标记
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
int dx1[]={1,1,1,0,0,-1,-1,-1};
int dy1[]={0,1,-1,1,-1,0,1,-1};
int n,m,ans;
void dfs(int x,int y){
	vis[x][y]=sc;
    for(int i=0;i<4;i++){ // 从上下左右遍历,将岛屿染色
		int nx=dx[i]+x;
		int ny=dy[i]+y;
		if(vis[nx][ny]||nx<1||nx>n||ny<1||ny>m||mp[nx][ny]=='0')continue;
		dfs(nx,ny);
	}
} 
bool query(int x,int y){
	if(x>n||x<1||y>m||y<1)return 1;
	v[x][y]=1;
	for(int i=0;i<8;i++){ // 观察是否能走到外海要从四面八方遍历
		int nx=dx1[i]+x;
		int ny=dy1[i]+y;
		if((mp[nx][ny]=='1'&&vis[nx][ny]!=sc)||v[nx][ny])continue; // 要沿着海域走,不能走到其他岛屿上,但是可以在本岛领土走
		if(query(nx,ny))return 1;
	}
	return 0;
}
void solve(){
    cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>mp[i][j];
			vis[i][j]=0;
		}
	}
	ans=0; // 全局变量 ans 归零
	sc=0; // 编号归零
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(vis[i][j]||mp[i][j]=='0')continue;
			sc++;
			dfs(i,j);
			for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)v[i][j]=0; // 将v标记全部还原为 0
			if(query(i,j))ans++; // 如果能走到外海就说明不是子岛屿
		}
	}
	cout<<ans<<endl;
}
int main() {
	ios::sync_with_stdio(false);                                                                       
	cin.tie(nullptr);
	int t=1;cin>>t;
	while(t--)solve();
	
}

评论

3 条评论,欢迎与作者交流。

正在加载评论...