Given an m x n matrix of positive integers representing the height of each unit cell in a 2D elevation map, compute the volume of water it is able to trap after raining.

Note:
Both m and n are less than 110. The height of each unit cell is greater than 0 and is less than 20,000.

Example:

1
2
3
4
5
6
7
8
Given the following 3x6 height map:
[
[1,4,3,1,3,2],
[3,2,1,3,2,4],
[2,3,3,2,3,1]
]
Return 4.


The above image represents the elevation map [[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]] before the rain.


After the rain, water are trapped between the blocks. The total volume of water trapped is 4.


主要思想就是从外围向内灌水,每次找到外围最小的点,如果它旁边有没访问过,且比当前值小的点,可以灌水,否则不可以,然后更新外围,用新的点的坐标和max(x, nx)做为值.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
class Cell implements Comparable<Cell> {
public int x, y, h;
public Cell(int x, int y, int h) {
this.x = x;
this.y = y;
this.h = h;
}
@Override
public int compareTo(Cell that) {
return this.h - that.h;
}
}
int[] dx = {0, 0, 1, -1};
int[] dy = {1, -1, 0, 0};
public int trapRainWater(int[][] heightMap) {
if (heightMap == null || heightMap.length == 0)
return 0;
if (heightMap[0] == null || heightMap[0].length == 0)
return 0;
int m = heightMap.length;
int n = heightMap[0].length;
PriorityQueue<Cell> pq = new PriorityQueue<>();
boolean[][] visited = new boolean[m][n];
int ans = 0;
for (int j = 0; j < n; j++) {
visited[0][j] = true;
pq.add(new Cell(0, j, heightMap[0][j]));
visited[m - 1][j] = true;
pq.add(new Cell(m - 1, j, heightMap[m - 1][j]));
}
for (int i = 1; i < m - 1; i++) {
visited[i][0] = true;
pq.add(new Cell(i, 0, heightMap[i][0]));
visited[i][n - 1] = true;
pq.add(new Cell(i, n - 1, heightMap[i][n - 1]));
}
while (!pq.isEmpty()) {
Cell min = pq.poll();
for (int i = 0; i < 4; i++) {
int nx = min.x + dx[i];
int ny = min.y + dy[i];
if (nx >= 0 && nx < m && ny >= 0 && ny < n && visited[nx][ny] == false) {
int h = heightMap[nx][ny];
visited[nx][ny] = true;
pq.offer(new Cell(nx, ny, Math.max(h, min.h)));
ans += Math.max(0, min.h - h);
}
}
}
return ans;
}