AcWing||AcWing 1233. 全球变暖
活动地址:https://www.acwing.com/activity/content/19/
考察要点:Flood Fill , BFS ,DFS
题目要求:1233. 全球变暖
题目放上了会有错位等问题,所以建议去原站看
题目地址:https://www.acwing.com/problem/content/1235/
解析:
求最后被淹没的岛的数量,
岛的定义是”上下左右”四个方向上连在一起的一片陆地组成一座岛屿
岛屿之间没有陆地连接(上下左右没有陆地连接,斜边不算)
被淹没的陆地是与海有直接连接的陆地(上下左右有一块与海连接 就会被淹没)
代码思路 :首先要解决的问题就是要求岛屿的数量,然后求出没有被淹没的岛屿数量。
求岛屿的数量:遍历地图,找到一块陆地,如果没有访问过,就进行 bfs 找出所有的与之相连的陆地(都标记访问过),这样一次 bfs 就会找出一座岛。
如何判断岛屿有没有淹没:
- 可以查看岛屿中不会淹没的陆地
- 求出岛屿陆地的数量 和岛屿中靠海的陆地数量,两个对比就可以找出有没有四面是陆地了
查找不会淹没的陆地代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
char g[N][N];
bool st[N][N];
typedef pair<int, int> PII;
#define x first
#define y second
PII q[N * N];
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};
int n;
bool bfs(int a, int b)
{
int head = 0, tail = 0; //用于模拟队列
q[0] = {a, b}; //入队列
st[a][b] = true; //将该点变成已访问
bool OverLand = true; //初始化岛屿会被淹没 如果找到不会被淹没的块 就置为false
while (head <= tail)
{
PII t = q[head ++]; //存储 出队列后移
bool isLand = true; //初始化该陆地不会被淹没
for (int i = 0; i < 4; i ++ )
{
int x = t.x + dx[i], y = t.y + dy[i];
if(x < 0 || x >= n || y < 0 || y >= n || st[x][y]) continue; //出界 和 访问过 跳过
if(g[x][y] == '.') {isLand = false; continue;} //如果旁边有海洋 就会被淹没
//else 就是陆地
q[++ tail] = {x, y}; //陆地入队列 队尾后移
st[x][y] = true; //入队列就是访问过
}
if(isLand) OverLand = false; //如果陆地不会被淹没 那么记录
}
// cout << unOverLand << endl;
if(OverLand) return true; //被淹没 返回true
return false; //不会被淹没 返回 false
}
int main()
{
cin >> n;
for (int i = 0; i < n; i ++ ) scanf("%s",g[i]);
int res = 0;
for (int i = 0; i < n; i ++ )
for (int j = 0; j < n; j ++ )
if(g[i][j] == '#' && !st[i][j])
{
//int total = 0, bound = 0;
//bfs(i, j, total, bound); //每次bfs都会将一个岛完全搜完,并得到陆地数量和靠海陆地数量
if(bfs(i, j)) res ++; //如果相等,那个就完全淹没
}
cout << res << endl;
return 0;
}
比较 陆地总数 和 靠海的陆地数量 代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
char g[N][N];
bool st[N][N];
typedef pair<int, int> PII;
#define x first
#define y second
PII q[N * N];
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};
int n;
void bfs(int a, int b, int &total, int &bound)
{
int head = 0, tail = 0; //用于模拟队列
q[0] = {a, b}; //入队列
st[a][b] = true; //将该点变成已访问
while (head <= tail)
{
PII t = q[head ++]; //存储 出队列后移
total ++ ; //陆地数量++
bool isBound = false;
for (int i = 0; i < 4; i ++ )
{
int x = t.x + dx[i], y = t.y + dy[i];
if(x < 0 || x >= n || y < 0 || y >= n || st[x][y]) continue; //出界 和 访问过的情况 就跳过
if(g[x][y] == '.') {isBound = true; continue;} //如果旁边是海洋 就 记录下来 然后跳过
//else 就是陆地
q[++ tail] = {x, y}; //陆地入队列 队尾后移
st[x][y] = true; //入队列就是访问过
}
if(isBound) bound ++; //如果靠近海,则靠近海的陆地数量 ++
}
}
int main()
{
cin >> n;
for (int i = 0; i < n; i ++ ) scanf("%s",g[i]);
int res = 0;
for (int i = 0; i < n; i ++ )
for (int j = 0; j < n; j ++ )
if(g[i][j] == '#' && !st[i][j])
{
int total = 0, bound = 0;
bfs(i, j, total, bound); //每次bfs都会将一个岛完全搜完,并得到陆地数量和靠海陆地数量
if(total == bound) res ++; //如果相等,那个就完全淹没
}
cout << res << endl;
return 0;
}
本题:1233. 全球变暖
代码参考:视频讲解