链接:https://leetcode-cn.com/problems/regions-cut-by-slashes/
在由 1 x 1 方格组成的 N x N 网格 grid
中,每个 1 x 1 方块由 /
、\
或空格构成。这些字符会将方块划分为一些共边的区域。
(请注意,反斜杠字符是转义的,因此 \
用 "\\"
表示。)。
返回区域的数目。
示例 1:
输入: [ " /", "/ " ] 输出:2 解释:2x2 网格如下:
示例 2:
输入: [ " /", " " ] 输出:1 解释:2x2 网格如下:
示例 3:
输入: [ "\\/", "/\\" ] 输出:4 解释:(回想一下,因为 \ 字符是转义的,所以 "\\/" 表示 \/,而 "/\\" 表示 /\。) 2x2 网格如下:
示例 4:
输入: [ "/\\", "\\/" ] 输出:5 解释:(回想一下,因为 \ 字符是转义的,所以 "/\\" 表示 /\,而 "\\/" 表示 \/。) 2x2 网格如下:
示例 5:
输入: [ "//", "/ " ] 输出:3 解释:2x2 网格如下:
提示:
1 <= grid.length == grid[0].length <= 30
grid[i][j]
是'/'
、'\'
、或' '
思路:本题如果直接考虑/和\是很难做的,因为这两者直接存在重合部分:
因此我们不如就从这个重合部分出发,将每一个小方格划分成四个部分:
于是这个题目可以分为两步:
1. 单元格内的三角形合并
A. / 型 此时单元格内应该合并 0-1,2-3
B. \ 型 此时单元格内应该合并 0-3,1-2
c. 空格 型 此时单元格内应该合并 0-1-2-3
2. 单元格之间的合并(为了不重复合并操作,我们可以向左向上或者向右向下)
A.向左合并
可以看到,实际上不管是三种图形中的哪一个,都可以向左合并,合并块始终是3(左)-1(右)。
B.向上合并
请读者自行分析,分析后的结果只需要合并2(上)-0(下)。
注:三角形块索引转换 index = ( i * N + j ) * 4 + which。
class Solution {
public:
int Father[4 * 30 * 30 + 10];
int Find(int x){
return x == Father[x] ? x : Father[x] = Find(Father[x]);
}
void Union(int A, int B, int& sum){
A = Find(A);
B = Find(B);
if(A != B){
-- sum;
Father[A] = B;
}
}
int regionsBySlashes(vector<string>& grid) {
int N = grid.size(), i, j, sum = 4 * N * N,grid0,grid1,grid2,grid3;
for(i = 0; i < N; ++ i){
for(j = 0; j < N; ++ j){
// 空格-4个子块均相连
grid0 = (i * N + j) * 4 + 0;
Father[grid0] = grid0;
grid1 = (i * N + j) * 4 + 1;
Father[grid1] = grid1;
grid2 = (i * N + j) * 4 + 2;
Father[grid2] = grid2;
grid3 = (i * N + j) * 4 + 3;
Father[grid3] = grid3;
switch(grid[i][j]){
case '/':Union(grid0, grid1, sum);
Union(grid2, grid3, sum);
break;
case '\\':Union(grid0, grid3, sum);
Union(grid1, grid2, sum);
break;
case ' ':Union(grid0, grid1, sum);
Union(grid0, grid2, sum);
Union(grid0, grid3, sum);
break;
}
// 向左向上连接
if(j > 0){ // 向左
Union(grid1, (i * N + j - 1) * 4 + 3, sum);
}if(i > 0){ // 向上
Union(grid0, ((i - 1) * N + j) * 4 + 2, sum);
}
}
}
return sum;
}
};