(dfs+模拟)2018年蓝桥杯C/C++A组省赛真题8全球变暖

题目

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


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

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

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

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


  …
  …
  …
  …#…
  …
  …

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

照片保证第1行、第1列、第N行、第N列的像素都是海洋。
输出格式
  一个整数表示答案。
样例输入
7

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

样例输出
1

分析

一个#和所有与它相连的#组成一块岛屿,这里的相连指的是上下左右,那我们可以先计算出来变化前的岛屿数量,然后模拟变化被淹没的岛屿,然后在计算变化后的岛屿数量,然后相减即是答案,计算岛屿的数量需要用到dfs标记一个岛屿的所有陆地,变化就需要模拟+判断即可

代码部分

1.循环遍历

遍历整个地图,如果出现#就计数加一,然后dfs标记和它相连的所有#

	cin>>n;
	vector<vector<char> > _map(n,vector<char>(n));	//地图
	vector<vector<bool> > vis(n,vector<bool>(n,0)); 	//标记 
	
	
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			cin>>_map[i][j];
	int oldcnt=0;
	
	for(int i=0;i<n;i++)	//计算变化前岛屿数量 
	{
    
    
		for(int j=0;j<n;j++)
		{
    
    
			if(_map[i][j]=='#'&&vis[i][j]==0)
			{
    
    
				oldcnt++;
				dfs(i,j,_map,vis); 
			}
		}
	}
2.dfs

我们首先要清楚dfs做的事情,从当前位置出发标记所有相连的#,分别是上下左右四个方向,所以为了简便我们开两个一维的数组作为方向坐标代表方向的变化,然后就是遍历四个方向,加判断下一个位置是否能走是否合法,每次标记当前的位置为已经走过

const int dx[4]={
    
    0,0,1,-1};		//方向 
const int dy[4]={
    
    1,-1,0,0};

void dfs(int x,int y,vector<vector<char> > &_map,vector<vector<bool> > &vis)
{
    
    
	//出口
	vis[x][y]=1;
	//现在能做的事情
	for(int i=0;i<4;i++)
	{
    
    
		if(x+dx[i]>=0&&x+dx[i]<n&&y+dy[i]>=0&&y+dy[i]<n&&
		vis[x+dx[i]][y+dy[i]]==0&&
		(_map[x+dx[i]][y+dy[i]]=='#'||_map[x+dx[i]][y+dy[i]]=='!'))
		{
    
    
			dfs(x+dx[i],y+dy[i],_map,vis);
		}
	}
}
3.模拟判断整个地图

之前我是模拟判断当前位置如果会被淹没我就把它改变成.,后来发现这样是不行的,最后地图中所有的格子都会被变成.,然后我将要淹没的格子改变成了!

bool check(int x,int y,vector<vector<char> > &_map)	//判断该岛屿是否会被淹没 
{
    
    
	for(int i=0;i<4;i++)
	{
    
    
		if(x+dx[i]>=0&&x+dx[i]<n&&y+dy[i]>=0&&y+dy[i]<n)
		{
    
    
			if(_map[x+dx[i]][y+dy[i]]=='.')
				return true;
		}
	}
	return false;	
}

	for(int i=0;i<n;i++)		//改变地图标记被淹没的陆地 
	{
    
    
		for(int j=0;j<n;j++)
		{
    
    
			if(_map[i][j]=='#'&&check(i,j,_map))
			{
    
    
				_map[i][j]='!';
			} 
		}
	}	
4.判断变化后的岛屿数量

如果我们直接像之前那样计算岛屿数量是不行的,因为有的岛屿变化后,如果直接计算会变成两个岛屿,这里题中给定的含义不是很清楚,所以我们判断的时候从#出发,但是!的地方也要进行标记和判断,因为这些陆地之前都是属于一个岛屿

	vector<vector<bool> > vis2(n,vector<bool>(n,0)); 	//标记 
	int nowcnt=0;
	
	for(int i=0;i<n;i++)	//计算变化后岛屿数量 
	{
    
    
		for(int j=0;j<n;j++)
		{
    
    
			if(_map[i][j]=='#'&&vis2[i][j]==0)
			{
    
    
				nowcnt++;
				dfs(i,j,_map,vis2); 
			}
		}
	}

完整代码

#include <bits/stdc++.h>
using namespace std;

int n;
const int dx[4]={
    
    0,0,1,-1};		//方向 
const int dy[4]={
    
    1,-1,0,0};

void dfs(int x,int y,vector<vector<char> > &_map,vector<vector<bool> > &vis)
{
    
    
	//出口
	vis[x][y]=1;
	//现在能做的事情
	for(int i=0;i<4;i++)
	{
    
    
		if(x+dx[i]>=0&&x+dx[i]<n&&y+dy[i]>=0&&y+dy[i]<n&&
		vis[x+dx[i]][y+dy[i]]==0&&
		(_map[x+dx[i]][y+dy[i]]=='#'||_map[x+dx[i]][y+dy[i]]=='!'))
		{
    
    
			dfs(x+dx[i],y+dy[i],_map,vis);
		}
	}
}

bool check(int x,int y,vector<vector<char> > &_map)	//判断该岛屿是否会被淹没 
{
    
    
	for(int i=0;i<4;i++)
	{
    
    
		if(x+dx[i]>=0&&x+dx[i]<n&&y+dy[i]>=0&&y+dy[i]<n)
		{
    
    
			if(_map[x+dx[i]][y+dy[i]]=='.')
				return true;
		}
	}
	return false;	
}

int main (void)
{
    
    
	cin>>n;
	vector<vector<char> > _map(n,vector<char>(n));	//地图
	vector<vector<bool> > vis(n,vector<bool>(n,0)); 	//标记 
	
	
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			cin>>_map[i][j];
	int oldcnt=0;
	
	for(int i=0;i<n;i++)	//计算变化前岛屿数量 
	{
    
    
		for(int j=0;j<n;j++)
		{
    
    
			if(_map[i][j]=='#'&&vis[i][j]==0)
			{
    
    
				oldcnt++;
				dfs(i,j,_map,vis); 
			}
		}
	}
	
	
	for(int i=0;i<n;i++)		//改变地图标记被淹没的陆地 
	{
    
    
		for(int j=0;j<n;j++)
		{
    
    
			if(_map[i][j]=='#'&&check(i,j,_map))
			{
    
    
				_map[i][j]='!';
			} 
		}
	}		

/*	
	for(int i=0;i<n;i++)		//输出改变后的地图 
	{
		for(int j=0;j<n;j++)
		{
			cout<<_map[i][j];
		}
		cout<<endl;
	}
*/	
	
	vector<vector<bool> > vis2(n,vector<bool>(n,0)); 	//标记 
	int nowcnt=0;
	
	for(int i=0;i<n;i++)	//计算变化后岛屿数量 
	{
    
    
		for(int j=0;j<n;j++)
		{
    
    
			if(_map[i][j]=='#'&&vis2[i][j]==0)
			{
    
    
				nowcnt++;
				dfs(i,j,_map,vis2); 
			}
		}
	}
	cout<<oldcnt-nowcnt;
	
	return 0;
}

总结

虽然这道题代码量很多,但是有很多地方都是重复的,思想也并不难,只是基础的dfs,但是有一些细节还是需要注意的

猜你喜欢

转载自blog.csdn.net/weixin_46035615/article/details/123967649