题目:
给定一个 m 行 n 列的二维地图,初始化每个单元格都是海洋,二维地图外也全是海洋。 操作 addLand 会将单元格(col, row)变为陆地。 定义一系列相连的被海洋包围的陆地为岛屿, 横向相邻或者纵向相连的岛屿才算相连(斜着相邻的不算)。 现有一系列的 addLand 操作,给出每次 addLand 操作后岛屿的个数。 |
样例:
|
1 1 2 3 |
思路:
根据题意,我们是要找到 连通块有多少个,就是多少个岛屿。
由于数据范围较小,所以我们可以使用 BFS 搜索,每一次放生成大陆后直接暴力查找连通块输出即可,而 非法坐标的情况,我们可以直接忽略。
代码详解如下:
#include <iostream>
#include <queue>
#include <cstring>
#define endl '\n'
#define x first
#define y second
#define mk make_pair
#define YES puts("YES")
#define NO puts("NO")
#pragma GCC optimize(3,"Ofast","inline")
#define ___G std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
using namespace std;
const int N = 500;using PII = pair<int,int>;// 控制查找的时候走动的方向
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};int n,m; // 地图大小
bool g[N][N]; // 地图内容
bool vis[N][N]; // 查找的时候标记是否查找过
int k; // 操作数int ans; // ans 是检查岛屿结果// 查找走动方向
inline bool isRun(int x,int y)
{return (x >= 0 && x < n && y >= 0 && y < m && !vis[x][y] && g[x][y]);
}inline void BFS(int x,int y)
{// 存储检查坐标queue<PII>q;q.push(mk(x,y));while(q.size()){// 取出当前坐标auto now = q.front();q.pop();// 标记已检查大陆坐标vis[now.x][now.y] = true;// 开始尝试往上下左右四个方向// 寻找大陆所形成的岛屿for(int i = 0;i < 4;++i){// 取出下一步检查的坐标int bx = now.x + dx[i];int by = now.y + dy[i];// 判断是否符合检查走动的条件if(isRun(bx,by)){// 符合则开始标记vis[bx][by] = true;// 列入下一步检查点q.push(mk(bx,by));} } }return ;
}inline void solve()
{// 控制输出格式bool st = false;cin >> n >> m >> k;while(k--){// 开始放置大陆int x,y;cin >> x >> y;// 控制的空格输出格式if(st) putchar(' ');// 如果坐标合法,那么开始放置大陆if(x >= 0 && x < n && y >= 0 && y < m){// 每次放置大陆的时候,我们都要重新// BFS 一遍查找连通块,所以这里要初始化标记ans = 0;memset(vis,false,sizeof vis);// 放置大陆g[x][y] = true;for(int i = 0;i < n;++i){for(int j = 0;j < m;++j){// 如果该大陆没被检查过if(!vis[i][j] && g[i][j]){// 累加岛屿++ans;// 开始检查BFS(i,j);}}} // 输出岛屿数量结果cout << ans;}else{// 如果做标是非法情况,那么我们直接输出上一次的检查结果cout << ans;}// 控制输出格式st = true;}
}int main()
{
// freopen("a.txt", "r", stdin);
// ___G;int _t = 1;
// cin >> _t;while (_t--){solve();}return 0;
}