zoukankan      html  css  js  c++  java
  • [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 }
  • 相关阅读:
    android外存文件读写
    android内存文件读写
    SearchView的使用
    Notification的使用(待完善)-〉添加点击取消,显示优化
    列表Dialog和“确认”、“取消”Dialog
    PopupWindow弹出窗口的使用
    侧拉菜单
    腾讯分析移动设备屏幕分辨率分析报告--转
    git hub使用
    input 原始版,后面修改
  • 原文地址:https://www.cnblogs.com/deadend/p/6665652.html
Copyright © 2011-2022 走看看