蓝桥杯2023年第十四届省赛真题-岛屿个数(双bfs,过过过!)

    由样例可以得知,我们需要统计的是“外岛个数”,对于内部岛屿我们并不需要统计,对于外岛的状态标记我们可以用bfs来进行标记,但是关键点就在于如何准确寻找到外岛边缘并进行标记,又由图可以得知,如果有外岛存在,那么海域将会分隔,也就是说内部的海域在8个方向上都没能访问到外部海域,这就是其中一个突破点,因此我们可以引入“外海”概念,我们可以对原图进行拓展,在其余空白区域都标记为‘0’,作为外海,图像如下:

对于外海,我们可以用bfs逐一标记,并且遇到陆地的时候,进行另一个bfs,把当前的外岛进行标记,因为外海无法访问被环形岛围住的内海,因此不必担心会访问到内岛,需要特别注意的是对于每个变量的初始化,因为这道题目是多次询问多次操作,上一次的图可能会影响到下一次的图,因此要注意初始化而对于统计外岛的个数,我们可以用全局变量cent来统计进入统计陆地的bfs的次数来获取答案

代码如下:

#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<string>
#define x first
#define y second//方便表示

using namespace std;

typedef pair <int, int> PII;
queue<PII> q;//对于海洋的
queue<PII> q1;//对于陆地的
const int N = 55;
char g[N][N];//存储地图
int T;//询问次数
int n, m;
bool st_sea[N][N];//存储每一块海的访问状态,如果访问过,那就是1,反之为0
bool st_load[N][N];//存储每一块陆地的访问状态,如果访问过,那就是1,反之为0
int dx[] = { 0,0,1,-1,1,1,-1,-1 };
int dy[] = { 1,-1,0,0,1,-1,1,-1 };
int cent = 0;//cent用于计数,一共有多少次进行访问陆地

void bfs_load(int x1, int y1)
{
	while (!q1.empty()) q1.pop();//先对队列进行清空
	q1.push({ x1,y1 });
	st_load[x1][y1] = 1;
	cent++;//对cent进行计数

	while (!q1.empty()) {
		auto t = q1.front(); q1.pop();
		for (int i = 0; i < 4; i++) {
			int a = t.x + dx[i], b = t.y + dy[i];
			if (a < 0 || a > m + 1 || b < 0 || b > n + 1) continue;//如果越界,那就跳过
			if (st_load[a][b]) continue;//如果访问过,那就跳过
			if (g[a][b] != '1') continue;//如果当前不是陆地,就跳过
			st_load[a][b] = st_load[t.x][t.y];
			q1.push({ a,b });
		}
	}

	return;
}

void bfs_sea(int x1, int y1)
{
	memset(st_load, false, sizeof(st_load));//初始化陆地状态
	memset(st_sea, false, sizeof(st_sea));//初始化海洋状态
	q.push({ x1,y1 });
	st_sea[x1][y1] = 1;//初始化
	while (!q.empty()) {
		auto t = q.front(); q.pop();
		for (int i = 0; i < 8; i++) {
			int a = t.x + dx[i], b = t.y + dy[i];
			if (a < 0 || a > m + 1 || b < 0 || b > n + 1) continue;//如果越界,那就跳过
			if (st_sea[a][b]) continue;//如果访问过,那就跳过
			if (g[a][b] == '1' && !st_load[a][b]) bfs_load(a, b);//如果当前是陆地,并且没有访问过,那就进入bfs来标记陆地
			if (g[a][b] != '0') continue;//如果当前不是海洋,就跳过
			st_sea[a][b] = st_sea[t.x][t.y];//对海洋进行标记
			q.push({ a,b });
		}
	}

	return;
}

int main(void)
{
	
	cin >> T;
	while (T--) {
		memset(g, '0', sizeof(g));//初始化地图
		while (!q.empty()) {
			q.pop();
		}//对q进行清空
		cent = 0;//初始化cent

		cin >> m >> n;
		
		for (int i = 1; i <= m; i++) {
			string line;
			cin >> line;
			for (int j = 0; j < n; j++) {//直接用cin读入char类型二维数组会受到换行符的影响,因此可以用string类型读入一行,再每个字符进行处理
				g[i][j + 1] = line[j];
			}
		}
		
		bfs_sea(0, 0);

		cout << cent << endl;
	}

	return 0;
}

案例也是全部通过了

 希望对你有所帮助

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值