首页 > 代码库 > [Offer收割]编程练习赛11 题目3 : 岛屿3

[Offer收割]编程练习赛11 题目3 : 岛屿3

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

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个整数,依次是当周末岛屿的数量、总面积和总周长。

样例输入
3  
0 0   
1 1   
1 0
样例输出
1 1 4  
2 2 8  
1 3 8 

思路

并查集。岛屿个数为并查集集合个数a,面积为陆地方格个数b,周长为方格总周长减去重叠长度 4 * b - 2 * 重叠边数。

代码

 1 import java.util.Scanner;
 2 
 3 public class Main {
 4 
 5     static class UF {
 6         int count;
 7         int[] parent;
 8 
 9         public UF(int n) {
10             parent = new int[n];
11             for (int i = 0; i < n; i++) {
12                 parent[i] = i;
13             }
14         }
15 
16         public int find(int id) {
17             while (parent[id] != id) {
18                 parent[id] = parent[parent[id]];
19                 id = parent[id];
20             }
21             return id;
22         }
23 
24         public void union(int pid, int qid) {
25             int proot = find(pid);
26             int qroot = find(qid);
27             if (proot != qroot) {
28                 count--;
29                 parent[proot] = qroot;
30             }
31         }
32     }
33 
34     private static int L = 1000;
35 
36     private static int[][] dir = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
37 
38     private static boolean reachable(int x, int y) {
39         return x >= 0 && y >= 0 && x < L && y < L;
40     }
41 
42     public static void main(String[] args) {
43         int[][] m = new int[L][L];
44         Scanner sc = new Scanner(System.in);
45         int n = sc.nextInt();
46         UF uf = new UF(L * L);
47         int area = 0;
48         int edges = 0;
49         while (n-- > 0) {
50             int x = sc.nextInt();
51             int y = sc.nextInt();
52             if (m[x][y] == 1) {
53                 continue;
54             }
55 
56             m[x][y] = 1;
57             uf.count++;
58             area++;
59 
60             int id = x * L + y;
61             for (int[] d : dir) {
62                 int nx = x + d[0];
63                 int ny = y + d[1];
64                 if (reachable(nx, ny) && m[nx][ny] == 1) {
65                     edges++;
66                     uf.union(id, nx * L + ny);
67                 }
68             }
69 
70             System.out.println(String.format("%d %d %d", uf.count, area, 4 * area - 2 * edges));
71         }
72     }
73 }

 

[Offer收割]编程练习赛11 题目3 : 岛屿3