每周一题(11)

每周一题(11)

全球变暖

你有一张某海域NxN像素的照片,".“表示海洋、”#"表示陆地,如下所示:
........##.....##........##...####....###........
其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有2座岛屿。
由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。
例如上图中的海域未来会变成如下样子:
................................#................
请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。

【输入格式】
第一行包含一个整数N。 (1 <= N <= 1000)
以下N行N列代表一张海域照片。
照片保证第1行、第1列、第N行、第N列的像素都是海洋。

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

【输入样例】
7

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

【输出样例】
1

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

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

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

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

题目来源

第九届蓝桥杯省赛B组

题解

      首先是定义所需变量:

char matrix[1005][1005];
int flag[1005][1005];
int N;
int d[4][2]={{1,0},{-1,0},{0,1},{0,-1}};

      其中N代表阶数,d[][]代表上下左右四个方向,matrix[][]表示陆地或海洋区域,flag[][]记录下其中位于陆地边缘的位置。
      在判断哪些位置位于陆地边缘时,根据题意只需要判断它的上下左右四个位置,只要这四个位置存在有海洋,就说明这是一个陆地边缘位置。为什么要设置一个flag[][]作为标记,是因为如果找到了边缘位置,直接将它变为海洋,那么位于它内部的陆地也会受到影响被判定是边缘陆地。所以为了使其他不受位置影响,需要一个标记来记录下,最近只将标记过的位置置为海洋就行。
      在标记过程中,我们只对陆地进行考虑,而且遍历时的下标都是从1开始的,因为题目要求输入不允许陆地出现在边界这种情况,所以也不需要考虑边界合法的问题。

void judge(){
	for(int x=1;x<N;x++){
		for(int y=1;y<N;y++){
			if(matrix[x][y]=='#')
				for(int i=0;i<4;i++){
					int nx=x+d[i][0], ny=y+d[i][1];
					if(matrix[nx][ny]=='.'){
						flag[x][y]=1;
						break;
					}
				}
		}
	}
}

      标记完边缘陆地,就可以进行更新,将边缘陆地变为海洋了。

void renew(){
	judge();
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			if(flag[i][j]==1){
				matrix[i][j]='.';
			}
		}
	}
}

      更新完岛屿以后,最后一步就是找到一共有多少块陆地。这里可以从任意‘#’开始,不停地把邻接的部分用‘.’代替。一次dfs后与初始的‘#’邻接的所有‘#’就都被替换了,直至图中不再具有‘#’。总共进行的dfs次数就是答案了。

void dfs(int x, int y){
	matrix[x][y]='*';
	for(int i=0;i<4;i++){
		int nx=x+d[i][0], ny=y+d[i][1];
		if(matrix[nx][ny]=='#')
			dfs(nx,ny);
	}
}
int solve(){
	int ans=0;
	for(int i=1;i<N;i++){
		for(int j=1;j<N;j++){
			if(matrix[i][j]=='#'){
				dfs(i,j);
				ans++;
			}
		}
	}
	return ans;
}

      全部示例如下:

#include<iostream>
using namespace std;
char matrix[1005][1005];
int flag[1005][1005];
int N;
int d[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
//标记出位于边缘的陆地 
void judge(){
	for(int x=1;x<N;x++){
		for(int y=1;y<N;y++){
			if(matrix[x][y]=='#')
				for(int i=0;i<4;i++){
					int nx=x+d[i][0], ny=y+d[i][1];
					if(matrix[nx][ny]=='.'){
						flag[x][y]=1;
						break;
					}
				}
		}
	}
}
//更新岛屿 
void renew(){
	judge();
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			if(flag[i][j]==1){
				matrix[i][j]='.';
			}
		}
	}
}
//深搜一片陆地 
void dfs(int x, int y){
	matrix[x][y]='*';
	for(int i=0;i<4;i++){
		int nx=x+d[i][0], ny=y+d[i][1];
		if(matrix[nx][ny]=='#')
			dfs(nx,ny);
	}
}
//找到几片陆地 
int solve(){
	int ans=0;
	for(int i=1;i<N;i++){
		for(int j=1;j<N;j++){
			if(matrix[i][j]=='#'){
				dfs(i,j);
				ans++;
			}
		}
	}
	return ans;
}
int main(){
	cin>>N;
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			cin>>matrix[i][j];
			flag[i][j]=0;
		}
	}
	renew(); 
	cout<<solve();
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值