[Offer收割]编程练习赛12 题目3 : 矩形分割
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
小Hi有一块由NxM个单位正方形组成的矩形。现在小Ho在某些单位正方形上画了一道分割线,这条分割线或者是单位正方形的主对角线(用'\'表示),或者是副对角线(用'/'表示)。
现在小Hi想知道这些分割线把NxM的矩形分割成了多少块区域。
例如
/\ \/
就把2x2的矩形分成了5个区域。
/\/\ \ / \/\
把3x4的矩形分成了7个区域。
输入
第一包含两个整数N和M。(1 <= N, M <= 100)
以下N行每行包含M个字符。每个字符只可能是/\或者空格。
输出
分割成的区域数目。
- 样例输入
-
3 4 /\/\ \ / \/\
- 样例输出
-
7
思路
(1)并查集。将每个位置用主对角线和反对角线分割成4块,以每一小块看做一个元素,利用并查集求解即可。
(2)DFS,BFS。分割方法与(1)相同,然后从每个未访问过的位置搜索、标记即可。
代码
1 import java.util.Scanner; 2 3 public class Main { 4 5 static class UF { 6 int[] parent; 7 int count; 8 9 public UF(int n) { 10 count = n; 11 parent = new int[n]; 12 for (int i = 0; i < n; i++) { 13 parent[i] = i; 14 } 15 } 16 17 public int find(int id) { 18 while (parent[id] != id) { 19 parent[id] = parent[parent[id]]; 20 id = parent[id]; 21 } 22 return id; 23 } 24 25 public void union(int pid, int qid) { 26 int proot = find(pid); 27 int qroot = find(qid); 28 if (proot != qroot) { 29 parent[proot] = qroot; 30 count--; 31 } 32 } 33 } 34 35 public static void main(String[] args) { 36 Scanner sc = new Scanner(System.in); 37 int m = sc.nextInt(); 38 int n = sc.nextInt(); 39 sc.nextLine(); 40 char[][] b = new char[m][]; 41 for (int i = 0; i < m; i++) { 42 b[i] = sc.nextLine().toCharArray(); 43 } 44 45 UF uf = new UF(n * m * 4); 46 for (int i = 0; i < m; i++) { 47 for (int j = 0; j < n; j++) { 48 int id = 4 * (i * n + j); 49 if (b[i][j] == '/' || b[i][j] == ' ') { 50 uf.union(id, id + 1); 51 uf.union(id + 2, id + 3); 52 } 53 54 if (b[i][j] == '\\' || b[i][j] == ' ') { 55 uf.union(id, id + 3); 56 uf.union(id + 1, id + 2); 57 } 58 59 if (j > 0) 60 uf.union(id, id - 2); 61 if (i > 0) 62 uf.union(id + 1, id - 4 * n + 3); 63 if (j < n - 1) 64 uf.union(id + 2, id + 4); 65 if (i < m - 1) 66 uf.union(id + 3, id + 4 * n + 1); 67 } 68 } 69 System.out.println(uf.count); 70 } 71 }