lanqiao178. 全球变暖(第九届蓝桥杯C++A组/B组) 或 acwing1233. 全球变暖

本文讲述了如何使用深度优先搜索(DFS)和广度优先搜索(BFS)算法解决岛屿淹没问题,介绍了字符数组输入的处理技巧,并列出了编程过程中的常见错误和优化建议。
摘要由CSDN通过智能技术生成

题目:

难点:

1. 读懂题目:到底有多少块岛屿 。按照题目的说法,并非是一个陆地的上下左右都有陆地,围成的才是岛屿。而是所有陆地都连在一起的才是一块岛屿(这些陆地之间没有海洋隔开)。

所以是两块岛屿。

2. 如何简单的判断岛屿会不会淹没:

①.进行思维转换,这道题可以想成 记录岛屿边的点数和总的点数,如果相等就是全是边,那么必然会被全淹没,否则不会。最后统计一下个数就行了

②.求的是被淹没的岛屿的数量=总岛屿数量-没淹没的岛屿的数量,如果一块岛屿里面的某一块陆地的四面都是陆地,那这个岛屿不会被淹没。注意:这样想有个误区,求没被淹没的岛屿容易出错,容易形成新的岛屿。比如下面这个图:

(一开始有两座岛屿,后来又是两座岛屿,这样求出的被淹没的岛屿数量就是错的)

(我不确定这样想是不是错的,如有错请指出)

3. 针对前面的方法一记录岛屿边的点数和总的点数:如何计算边数

只要'#'的四周出现'.'那么这就是边。

易错点:

1. 读入的是字符啊,我的老天爷,调试到最后才发现这个错误。

①. 要把数组定义为char类型

②. 如果用scanf("%c",&map[i][j]); 还是会错误,要处理好换行getchar();

   for(int i=0;i<n;i++)
		{
		    for(int j=0;j<n;j++)
		       {
                scanf("%c",&map[i][j]); 
                }
		    getchar();
		}

但奇怪的是蓝桥上可以通过所有测试点

acwing上他有些通不过,比如这个:

 换成cin来输入

for(int i = 0;i < n;i ++) 
        for(int j=0;j<n;j++)
             cin >> map[i][j];

2. bool st[N][N];  这个用来标志哪一个数字搜过没有。

3. 一般都是for(int i=0;i<4;i++)      左,上,右,下搜索,并更新map数组,但是这里有点不一样。

①. 如果这样写(错误写法):会导致搜到'.'之后不会继续搜索了,递归进行不下去,周边的其他陆地还要搜索呢。

for(int i=0;i<4;i++)      //左,上,右,下搜索
        {
            int nx=x+dx[i],ny=y+dy[i];      //更新
                {
                    if(total==brick)        //此刻遇到终点了 
                        {
                            cnt++;
                          
                        }
                    else if(map[nx][ny]=='.')
                        {
                            brick++;
                            break;  //并且不要再搜了 
                         } 
                    else if(map[nx][ny]=='#'&&!st[x][y])
                        {
                            total++;
                            dfs(nx,ny);
                        }
                 } 
         } 

②. 正确写法:要再重新走一次循环。

void dfs(int x,int y)
{
	st[x][y]=true;
	for(int i=0;i<4;i++)      //左,上,右,下搜索
		{
			if(map[x+dx[i]][y+dy[i]]=='.')
				{
					brick++;
					break;  //并且不要再搜了 
				} 
	    }
	for(int i=0;i<4;i++)  
		{int nx=x+dx[i],ny=y+dy[i];      //更新
			if(map[nx][ny]=='#'&&!st[nx][ny])
				{
					total++;
					dfs(nx,ny);
				}
		}
				
	
}

4. 不能把if(total==brick)
                                  cnt++;

也放到bfs的for循环里面,如果实际total>brick的话,也会在某个时间判断成total==brick

代码:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1010;
char map[N][N];
//int d[4][2] = {{-1,0},{0,-1},{1,0},{0,1}};//左,上,右,下
const int dx[] = {-1,0,1,0}, dy[] = {0,-1,0,1};//左,上,右,下
bool st[N][N];  // 这个用来标志哪一个数字搜过没有 
int total,brick,cnt=0;
void dfs(int x,int y)
{
	st[x][y]=true;
	for(int i=0;i<4;i++)      //左,上,右,下搜索
		{
			if(map[x+dx[i]][y+dy[i]]=='.')
				{
					brick++;
					break;  //并且不要再搜了 
				} 
	    }
	for(int i=0;i<4;i++)  
		{int nx=x+dx[i],ny=y+dy[i];      //更新
			if(map[nx][ny]=='#'&&!st[nx][ny])
				{
					total++;
					dfs(nx,ny);
				}
		}
				
	
}
int main()
{
	int n;
	scanf("%d",&n);
    /*for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
		    scanf("%c",&map[i][j]); */
	 for(int i = 0;i < n;i ++) 
	    for(int j=0;j<n;j++)
	         cin >> map[i][j];
	// int cnt=0;
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			{

						if(map[i][j]=='#'&&!st[i][j]) 
							{
								brick=0;
								total=1;
								dfs(i,j);
								if(total==brick)
								  cnt++;
							}

			}
	cout << cnt << endl;
	return 0;
}

优化代码:主要优化total的位置,其实不修改也行。

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1010;
char map[N][N];
//int d[4][2] = {{-1,0},{0,-1},{1,0},{0,1}};//左,上,右,下
const int dx[] = {-1,0,1,0}, dy[] = {0,-1,0,1};//左,上,右,下
bool st[N][N];  // 这个用来标志哪一个数字搜过没有 
int total,brick,cnt=0;
void dfs(int x,int y)
{ 
    total++;
	st[x][y]=true;
	for(int i=0;i<4;i++)      //左,上,右,下搜索
		{
			if(map[x+dx[i]][y+dy[i]]=='.')
				{
					brick++;
					break;  //并且不要再搜了 
				} 
	    }
	for(int i=0;i<4;i++)  
		{int nx=x+dx[i],ny=y+dy[i];      //更新
			if(map[nx][ny]=='#'&&!st[nx][ny])
				{
					dfs(nx,ny);
				}
		}
				
	
}
int main()
{
	int n;
	scanf("%d",&n);
    /*for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
		    scanf("%c",&map[i][j]); */
	 for(int i = 0;i < n;i ++) 
	    for(int j=0;j<n;j++)
	         cin >> map[i][j];
	// int cnt=0;
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			{

						if(map[i][j]=='#'&&!st[i][j]) 
							{
								total=brick=0;
								dfs(i,j);
								if(total==brick)
								  cnt++;
							}

			}
	cout << cnt << endl;
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值