全球变暖 BFS非递归【蓝桥杯真题】(c++实现)

254 阅读4分钟

上文链接:螺旋折线 一分钟解决 【蓝桥杯真题】(c++实现)


全球变暖

你有一张某海域NxN像素的照片,"."表示海洋、"#"表示陆地,如下所示:
.......
.##....
.##....
....##.
..####.
...###.
.......
其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有2座岛屿。

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

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

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

请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。
【输入格式】 第一行包含一个整数N。 (1 <= N <= 1000) 以下N行N列代表一张海域照片。

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

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

【输入样例】
7

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

【输出样例】
1

我的思路

  • 本题背景:一片连通的陆地" # "四周有水" . "的会被淹没,求完全被水淹没的连通陆地的个数。

  • 可以这样求解,通过广度优先遍历BFS查找地图,查找过程中记录某连通陆地中临近水的陆地数量和连通块里的陆地数量,如果二者相同那么该连通陆地会被淹没。

算法展示

运行正确、内存稍大(个人思路版):

 #include <iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>

using namespace std;

int N,ans;

char F_area[1000][1000];
int  M_area		[1000][1000];

//坐标的四周 
int Lx[] = {0,0,1,-1};
int Ly[] = {1,-1,0,0};

//存储坐标 
struct Point{
	int x,y;
};

void BFS(int i,int j)
{
	M_area[i][j] = 1;//标记该点已读 
	queue<Point> q;
	q.push({i,j});//将当前坐标存入队列 
	int cn1 = 0,cn2 = 0;//记录当前连通陆地的数量以及和水相邻的数量 
	while(!q.empty())
	{
		Point first  = q.front();
		q.pop();
		cn1 ++;//数量 
		bool swed = false;//标记该坐标四周是否有水 
		for(int k = 0;k<4;++k)//查找四周 
		{
			int x = first.x + Lx[k];
			int y = first.y + Ly[k];
			if(0<=x&&x<N&&0<=y&&y<N&&F_area[x][y]=='.')swed = true;
			if(0<=x&&x<N&&0<=y&&y<N&&F_area[x][y]=='#'&&M_area[x][y] ==0)
			{
				q.push({x,y});//与某陆地坐标相邻的陆地进入队列 
				M_area[x][y] = 1;
			}
		}
		
		if (swed)cn2++; //如果该坐标四周有水,则记录到临近水的陆地数量中 
	}
	if(cn1 == cn2)ans++;//某坐标点开始找,找完所有陆地 
}

int main()
{
	//快读配置 
	std::ios::sync_with_stdio(0);

	//读取规模 
	cin>>N;
	
	//读取地图 
	for(int i = 0;i<N;++i)
	{
		for(int j = 0;j<N;++j)
		{
			cin>>F_area[i][j];
		}
	}
	//进行广搜查找 
	for(int i = 0;i<N;++i)
	{
		for(int j = 0;j<N;++j)
		{
			if(M_area[i][j]==0&& F_area[i][j]=='#')//如果这个坐标是陆地且没有被访问过 
			{
				BFS(i,j);
			} 
		}
	}
	
	cout<<ans<<endl;;	
	return 0;
}	

运行正确、内存稍小(网上借鉴版):

#include <iostream>
#include<cstdio>
#include<queue>
using namespace std;
char ss[1005][1005];
const int ax[4]={1,0,-1,0};
const int ay[4]={0,1,0,-1};
struct point
{
    int x,y;
};
void rch(point w,queue<point>& dian,queue<point>& jin,int n)
{
    int i;
    point first;
    for(i=0;i<4;i++)
    {
        if((w.x+ax[i])>=1&&(w.x+ax[i])<=(n-2)&&(w.y+ay[i])>=1&&(w.y+ay[i])<=(n-2))
        {
            if(ss[w.x+ax[i]][w.y+ay[i]]=='.') 
            {
                first.x=w.x+ax[i];
                first.y=w.y+ay[i];
                dian.push(first);
                ss[w.x+ax[i]][w.y+ay[i]]='0';
            }
            else if(ss[w.x+ax[i]][w.y+ay[i]]=='#') 
            {
                first.x=w.x+ax[i];
                first.y=w.y+ay[i];
                jin.push(first);
                ss[w.x+ax[i]][w.y+ay[i]]='1';
            }
        }
    }
}
bool pan(int x,int y)
{
    int i;
    for(i=0;i<4;i++)
        if(ss[x+ax[i]][y+ay[i]]=='.'||ss[x+ax[i]][y+ay[i]]=='0') break;
    if(i>=4) return true;
    else return false;
}
void def(int n)
{
    queue<point> dian;
    queue<point> jin;
    bool flag=true;
    int ct=0;
    int num=0;
    point w;
    w.x=1;w.y=1;
    if(ss[1][1]=='.')    {dian.push(w);ss[1][1]='0';}
    else {jin.push(w);ss[1][1]='1';}
    while(!dian.empty()||!jin.empty())
    {
        if(!jin.empty()) 
        {
            ct++;
        }
        while(!jin.empty())
        {
            w=jin.front();
            jin.pop();
            if(flag&&pan(w.x,w.y)) {num++;flag=false;}
            rch(w,dian,jin,n);
        }
        flag=true;
        if(dian.empty()) break;
        else
        {
            w=dian.front();
            dian.pop();
            rch(w,dian,jin,n);
        }
    }
    cout<<ct-num<<"\n";
}
int main(int argc, char *argv[]) {
    int n;
    cin>>n;
    int i,j;
    ios::sync_with_stdio(false);
    for(i=0;i<n;i++)
        for(j=0;j<n;j++)
            cin>>ss[i][j];
    def(n);
    return 0;
}

下文链接:日志统计 巧用Vector,,map 【蓝桥杯真题】(c++实现)