hiho1487岛屿3

描述

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;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值