2018年蓝桥杯c/c++B组初赛(第九届)第九题-全球变暖

9.标题:全球变暖

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

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

.......

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

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

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

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

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

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

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

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

【输入样例】

7

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

【输出样例】
1

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

分析:用BFS搜岛屿,再减去剩下的。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
struct Node{
  int x,y;
  int num;
}Now,Next,S;//结构体记录信息,Now代表现在正在检测的,Next代表下一个要检测的,S用来传递之前输入进来的参数。
char MAP[1005][1005];//记录原始地图的情况
int vis[1005][1005];//用来标记的数组,0代表还没检测的地方,1代表海洋,2代表不会淹没的陆地
int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};//向四周检测,上下左右
int n,sum;

bool in(int x,int y){//检查这个坐标点是否在给定区域内,即判断有没有越界
  if(x >= 0 && y >= 0 && x < n && y < n)
     return true;
     return false;
}

bool Check(int x,int y){//用来检测坐标点四周的海洋陆地情况,有上下左右四个方向
  for(int i=0;i<4;i++){
    int X = x + dir[i][0];
    int Y = y + dir[i][1];
    if(MAP[X][Y] == '.' && in(X,Y))
       return true;
  }
    return false;
}

void bfs(){
  queue<Node> q;//声明一个队列
  S.num = sum;
  q.push(S);//将结构体S压入队列
  while(!q.empty()){
    Now = q.front();//获取队列中的第一个元素,即S
    q.pop();//弹出队列中第一个元素,即删除
    if(Check(Now.x,Now.y)){//检查周围是否有海水
       vis[Now.x][Now.y] = 1;//有的话用数组标记为1(刚开始都是0,表示陆地)
    }
    for(int i=0;i<4;i++){//向坐标点上下左右检测
      Next.x = Now.x + dir[i][0];
      Next.y = Now.y + dir[i][1];
      if(in(Next.x,Next.y) && MAP[Next.x][Next.y] == '#' && vis[Next.x][Next.y] != 1){//如果该点没有越界,且代表陆地,并且当前没有被淹时
        if(vis[Next.x][Next.y] == 0)//
           vis[Next.x][Next.y] = 2;//标记该点为不会被淹没的陆地
           Next.num = Now.num;//当前的岛屿数
           q.push(Next);//将当前的结构体压入队列底,表示为下一次检测提供坐标点
      }
    }
  }
  sum++;//每次检测完代表一个岛屿被找出并被标记,所以要加1
}

int main(){
    int i;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%s",MAP[i]);
    }
        memset(vis,0,sizeof(vis));
        sum = 0;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(MAP[i][j] == '#'){//处理陆地周边的情况
                  if(vis[i][j] != 0)//如果这个点检测完了,就继续下一个
                     continue;
                     S.x = i;//还没检测的话,就开始检测
                     S.y = j;
                     bfs();//将岛屿标记出来
                }
            }
        }
        for(int i=n-1;i>=0;i--){
            for(int j=n-1;j>=0;j--){
                if(MAP[i][j] == '#' && vis[i][j] == 2){//检测剩下的没有被淹没的岛屿数
                   sum--;//因为的求被淹没的岛屿数,所以是原来的减去剩下的
                }
            }
        }
                   printf("%d\n",sum>0?sum:0);//输出被淹没的岛屿数,如果岛屿没有减少,反而增加了,则输出0
                   return 0;
}





猜你喜欢

转载自blog.csdn.net/jxufe_acmer/article/details/80201653