一、Problem
給你一張某一海域衛星照片,你需要統計:
- 照片中海島的數目
- 照片中面積不同的海島數目
- 照片中形狀不同的海盜數目
其中海域的照片如下,".“表示海洋,”#"表示陸地。在"上下左右"四個方向上連在一起的一片陸地組成一座島嶼。
.####..
.....#.
####.#.
.....#.
..##.#.
上圖所示的照片中一共有4座島嶼;其中3座面積爲4,一座面積爲2,所以不同面積的島嶼數目是2;有兩座形狀都是"####",所以形狀不同的島嶼數目爲3。
輸入
第一行包含兩個人整數:N 和 M,(1 ≤ N, M ≤ 50),表示照片的行數和列數。
以下一個 N * M 的矩陣,表示表示海域的照片。
輸出
輸出3個整數,依次是照片中海島的數目、面積不同的海島數目和形狀不同的海島數目。
樣例輸入
5 7
.####..
.....#.
####.#.
.....#.
..##.#.
樣例輸出
4 2 3
二、Solution
方法一:dfs
- 求島嶼數量 num 是簡單的…
- 求島嶼面積的個數也不難,在搜索的時候保存陸地的 # 個數即可…
- 比較麻煩的是求島嶼的形狀,這裏有一種比較簡單的思路:
- 以第一行中
.####
爲例,各個島嶼的座標分別爲(0, 1)(0, 2)(0, 3)(0, 4)
,而相對於 (0, 1) 的相對座標爲(0, 0)(0, 1)(0, 2)(0, 3)
。 - 第三行的
"####"
的座標分別爲(2, 0)(2, 1)(2, 2)(2, 3)
,它們相對(2, 0)
的位置座標也是(0, 0)(0, 1)(0, 2)(0, 3)
- 結論:兩個島嶼的形狀相同當且僅當它們的相對位置序列完全相同。
- 以第一行中
- 可行的做法:
- 用二叉搜索樹保存每個座標的 hash 值。
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static class Solution {
int R, C;
char[][] grid;
final int[][] dir = { {1,0},{0,-1},{0,1},{-1,0} };
int hash(Pos t) {
return t.x*R+t.y;
}
void dfs(Pos c, Pos p, Set<Integer> set) {
set.add(hash(c) - hash(p));
for (int k = 0; k < 4; k++) {
int tx = c.x + dir[k][0];
int ty = c.y + dir[k][1];
if (!inArea(tx, ty) || grid[tx][ty] == '.')
continue;
grid[tx][ty] = '.';
dfs(new Pos(tx,ty), p, set);
}
}
void init() {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
R = sc.nextInt();
C = sc.nextInt();
grid = new char[R][C];
for (int i = 0; i < R; i++) {
String s = sc.next();
for (int j = 0; j < C; j++)
grid[i][j] = s.charAt(j);
}
int num = 0;
Set<Integer> area = new HashSet<>();
Set<Set<Integer>> shape = new HashSet<>();
for (int i = 0; i < R; i++)
for (int j = 0; j < C; j++) {
if (grid[i][j] == '#') {
Set<Integer> set = new HashSet<>(); //保存相對座標的數量
Pos t = new Pos(i, j);
dfs(t, t, set);
num++;
area.add(set.size());
shape.add(set);
}
}
System.out.printf("%d %d %d", num, area.size(), shape.size());
}
boolean inArea(int x, int y) {
return x >= 0 && x < R && y >= 0 && y < C;
}
class Pos {
int x, y;
Pos(int _x, int _y) {x = _x;y = _y;}
}
}
public static void main(String[] args) throws IOException {
Solution s = new Solution();
s.init();
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,
方法二:
複雜度分析
- 時間複雜度:,
- 空間複雜度:,