描述
H国正在进行一项持续N周的填海造岛工程。整片工程海域可以被看作是1000x1000的网格。
每周都有一块1x1的单位方格海域被填成陆地。如果我们将连成一片的陆地(一块单位方格与它上下左右4个单位方格是相连的)视为岛屿,H国想监测每周末整片海域中一共存在有多少个岛屿,以及这些岛屿的总面积和总周长各是多少。
假设工程持续三周,第一周被填的海域坐标是(0, 0),那么第一周结束后有1座岛屿、总面积是1、总周长是4:
#.. ... ...
第二周被填的海域坐标是(1, 1),那么第二周结束后有2座岛屿、总面积是2、总周长是8:
#.. .#. ...
第三周被填的海域坐标是(1, 0),那么第三周结束后有1座岛屿、总面积是3、总周长是8:
#.. ##. ...
你能完成这项任务么?
输入
第一行包含一个整数N,表示工程持续的周数。(1 <= N <= 100000)
以下N行每行包含两个整数x和y,表示当周被填的海域坐标。(0 <= x, y < 1000)
输出
输出N行,每行包含3个整数,依次是当周末岛屿的数量、总面积和总周长。
题意:在1000×1000的海域上填充陆地,每填充完一次,问当前的岛屿数,岛屿总面积,岛屿总周长。思路:既然一次只能填充一个小格,总面积一定自然数增长1,2,3,4,5……;周长,每个新增小正方形对
总周长贡4,如果小正方形与上下左右中的一个方向拼接则,总周长减小2。
总岛屿数就复杂点,因为可能新增的陆地连接起的多个方向是多个岛屿,也可以是1个岛屿。如何去判断几个方向
是否原本就属于一个岛屿,是需要解决的问题。可以把小方格陆地看成点集合,用并查集可以轻松解决。
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
const int N = 1100;
using namespace std;
typedef long long ll;
int dir[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
int fa[N*N];
bool rec[N][N];
void init()
{
for (int i = 0; i <= 1000000;i++)
fa[i] = i;
}
int find(int x)
{
return fa[x] == x ? x :(fa[x] = find(fa[x]));
}
int main()
{
int n;
while (~scanf("%d", &n))
{
memset(rec, 0, sizeof(rec));
init();
int cnt = 0, len = 0, sq = 0;
for (int i = 0; i < n; i++)
{
int x, y, id;
scanf("%d%d", &x, &y);
id = x*1000 + y;
cnt++;//新增一块陆地就是
//一个新岛屿,判断是否是别的岛屿时再修改
//岛屿数,将一个过程拆开统计
sq++;
len += 4;
rec[x][y] = true;
for (int i = 0; i < 4; i++)
{
int tx = x + dir[i][0], ty = y + dir[i][1];
if (tx >= 1000 || ty >= 1000 || tx < 0 || ty < 0 || rec[tx][ty] == 0)//不是岛屿不处理
continue;
int tid = tx * 1000 + ty;
int tmpid = find(tid);
int cid = find(id);
if (cid != tmpid)//不是一块岛就合并,同时修改总岛屿数
{
cnt--;
fa[cid] = tmpid;
}
len -= 2;
}
printf("%d %d %d\n", cnt, sq, len);
}
}
return 0;
}