2018蓝桥杯省赛B组-9.全球变暖

博客围绕蓝桥杯省赛的“全球变暖”问题展开,给出海域照片,因海面上升岛屿边缘会被淹没,需计算被完全淹没的岛屿数。解题不能用深搜,会爆栈,采用广搜标记岛屿号,更新地图后求剩余岛屿数,用开始岛屿数相减得沉没岛屿数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

标题:全球变暖

你有一张某海域NxN像素的照片,".“表示海洋、”#"表示陆地,如下所示:


.##…
.##…
…##.
…####.
…###.

其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有2座岛屿。

由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。

例如上图中的海域未来会变成如下样子:





…#…

请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。

【输入格式】
第一行包含一个整数N。 (1 <= N <= 1000)
以下N行N列代表一张海域照片。

照片保证第1行、第1列、第N行、第N列的像素都是海洋。

【输出格式】
一个整数表示答案。

【输入样例】
7

.##…
.##…
…##.
…####.
…###.

【输出样例】
1

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。

注意:
main函数需要返回0;
只使用ANSI C/ANSI C++ 标准;
不要调用依赖于编译环境或操作系统的特殊函数。
所有依赖的函数必须明确地在源文件中 #include
不能通过工程设置而省略常用头文件。

提交程序时,注意选择所期望的语言类型和编译器类型。

此题不能用深搜查连通块数,因为1000*1000很大,用深搜会爆栈。
用广搜就不会爆栈,因为最大栈为连通块最大一步的数量。

  1. 广搜出开始岛的数量,并分别标记岛屿号。
  2. 水位上涨更新地图。
  3. 枚举地图上的岛屿,并标记已存在岛屿,排除重复岛屿,求得实际剩余岛屿数量。
  4. 沉没岛屿数=开始岛屿数-实际剩余岛屿数。
  5. 提交代码,等待着绿色的降临。
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

int N,sum=0;
char map[1005][1005];
int mark[1005][1005]= {0};
int mark2[1000005]= {0};
int dir[4][2]= {{-1,0},{0,1},{1,0},{0,-1}};
struct node {
	int x,y;
};

void bfs(int x, int y) {
	queue<node> q;
	node head;
	head.x=x,head.y=y;
	q.push(head);
	while(!q.empty()) {
		head=q.front();
		q.pop();
		node next;
		for(int i=0; i<4; i++) {
			next.x=head.x+dir[i][0];
			next.y=head.y+dir[i][1];
			if(next.x<0||next.y<0||next.x>=N||next.y>=N||map[next.x][next.y]!='#'||mark[next.x][next.y]) continue;
			mark[next.x][next.y]=sum;
			q.push(next);
		}
	}
}

int  cover(int x,int y) {
	int flag=0;
	for(int i=0; i<4; i++) {
		int xx=x+dir[i][0];
		int yy=y+dir[i][1];
		if(xx>=0&&yy>=0&&xx<N&&yy<N&&map[xx][yy]=='.'&&mark[xx][yy]==0) {
			flag=1;
			break;
		}
	}
	return flag;
}

int main() {
	scanf("%d",&N);
	for(int i=0; i<N; i++) {
		getchar();
		scanf("%s",map[i]);
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(mark[i][j]==0&&map[i][j]=='#') {
				sum++;
				mark[i][j]=sum;
				bfs(i,j);
			}
		}
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(map[i][j]=='#'&&cover(i,j)) {
				map[i][j]='.';
			}
		}
	}

	int sum2=0;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(map[i][j]=='#'&&mark2[mark[i][j]]==0) {
				sum2++;
				mark2[mark[i][j]]=1;
			}
		}
	}

	printf("%d",sum-sum2);

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值