第九届-8-全球变暖

标题:全球变暖

【题目描述】
你有一张某海域NxN像素的照片,"."表示海洋、"#"表示陆地,如下所示:
.......
.##....
.##....
....##.
..####.
...###.
.......

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

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

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

【样例输入】

.......
.##....
.##....
....##.
..####.
...###.
.......  


【样例输出】
1  

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


问题分析:基本想法是用dfs搜索每一个岛屿,在搜索的同时判断这个岛屿中有没有陆地不会被淹没,如果没有结果就加1(注意结果要求的是被淹没陆地的数量)
判断岛屿的方法是枚举每一个像素,如果是陆地则深度搜索与之相连的陆地,属于同一个岛屿的陆地在visit中被标以相同的数值
如果一块陆地在淹没后仍然是陆地,那么在淹没前它的上下左右四个方向上应该都是陆地。

仍有疑问的地方是岛屿的定义是什么。按照我的程序的方法,有多块陆地相连即为岛屿。例如
..........
.####.....
..##......
..........
..........
..........
..##....#.
..##....#. 
........#.
..........
这个样例的岛屿数目为3,且都会被淹没
如果按照题干说法“上下左右四个方向上连在一起的一片陆地组成一座岛屿”,那么上述样例中应该只有2个岛屿且都会被淹没。
遗憾的是我还没找到与后者对应的编写方法。


以下代码仅仅是自己编写的,找不到OJ测试所以也不知道对不对。如果有知道可以测真题的OJ的朋友,希望可以给我推荐一下,感谢!

#include <iostream>
#include <cstring>
#include <set>
using namespace std;
const int MAX = 1000+10;

char p[MAX][MAX];
char copy[MAX][MAX];
int visit[MAX][MAX];
int n;
int landbefore = 0;
int res = 0;
bool iflive;

void dfs(int i,int j){
	if(visit[i][j] != 0)
		return;
	if(i<1 || j<1 || i>n || j>n)
		return;
	if(p[i][j] == '#'){
		visit[i][j] = landbefore;
		//如果当前正在深搜的岛屿中有陆地不会被淹没就把标记置为true 
		if(p[i-1][j] == '#' && p[i+1][j] == '#'&& p[i][j-1] == '#' && p[i][j+1] == '#')
			iflive = true;
		dfs(i-1,j);
		dfs(i+1,j);
		dfs(i,j-1);
		dfs(i,j+1);
	}		
}

int main(){
	cin >> n;
	for(int i = 1;i<=n;i++)
		for(int j = 1;j<=n;j++)
			cin >> p[i][j];
	memset(visit,0,sizeof(visit));
	int pc = 0;
	for(int i = 1;i<=n;i++)
		for(int j = 1;j<=n;j++){
			if(p[i][j] == '#'){
				
				if(visit[i][j] == 0){
					iflive = false;
					landbefore++;
					dfs(i,j);
					//标记仍未false说明这块岛屿没有剩下的,也就是被淹没了 
					if(!iflive)
						res++;
					
				}	
			}
		}	
	cout << res << endl;	
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值