题目描述
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:
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.
求出凹陷下去的地方能盛的水体积
解题思路
虽然是bfs的标签,但是因为第一次接触这种类型题,完全无思路(毕竟是hard),然后,发现了一位大神图文并茂的解题说明(感激!):
Grandyang的博客(我只是参考了解题思路,代码是自己写的)
一个方块能装水,那么它的四周都必须是比它高的方块,因此,bfs的应用就是,取出一个方块,遍历它外围的四块方块。然而,题目并不是那么简单。这道题还用到了优先队列(每次挑选高度最小的出队,和一般的bfs不一样,优先队列参考内容:ZXH小朋友的上学史 的博客)以及模拟海平面上升的方法(Grandyang 博客里有):海平面初始值为1,取出priorityqueue的top元素,若是 高度 > 海平面,则用这个值更新海平面,遍历元素四周的方块,低于海平面,则可装的水是海平面 - 方块高度。
好了,现在对整个解题过程进行总结:
一、主要准备:
1、priority queue (forBFS):装有最外围一圈方块,并以高度从小到大出队。
2、海平面(seaRevel):方块装水的参照,装水量:海平面 - 方块高度
3、代表元素坐标、高度的box
4、代表box四周方块的坐标偏移量pos{(1,0),(0,1),(-1,0),(0,-1)}(要注意越界问题)
二、核心思路:
出队一个box,判断四周方块是否被访问过,如果没有,把方块入队,置visited = true。判断遍历的方块与海平面的关系,能装的水:海平面 - 方块高度。
代码如下:
class Solution {
public:
struct Box {
int x;
int y;
int height;
Box(int a, int b, int c) :x(a), y(b), height(c) {
}
bool operator < (const Box& b) const {
return b.height < height;
}
};
int trapRainWater(vector<vector<int>>& heightMap) {
if (heightMap.size() == 0) {
return 0;
}
int rowCount = heightMap.size();
int colCount = heightMap[0].size();
priority_queue<Box> forBFS;
vector<bool> tmp(colCount, false);
vector<vector<bool> >visited(rowCount, tmp);
for (int i = 0; i < colCount; i++) {
if (!visited[0][i]) {
forBFS.push(Box(0, i, heightMap[0][i]));
visited[0][i] = true;
}
if (!visited[rowCount - 1][i]) {
forBFS.push(Box(rowCount - 1, i, heightMap[rowCount - 1][i]));
visited[rowCount - 1][i] = true;
}
}
for (int j = 0; j < rowCount; j++) {
if (!visited[j][0]) {
forBFS.push(Box(j, 0, heightMap[j][0]));
visited[j][0] = true;
}
if (!visited[j][colCount - 1]) {
forBFS.push(Box(j, colCount - 1, heightMap[j][colCount - 1]));
visited[j][colCount - 1] = true;
}
}
int seaRevel = 0;
int water = 0;
vector<pair<int, int> > pos;
pos.push_back(pair<int, int>(0, 1));
pos.push_back(pair<int, int>(1, 0));
pos.push_back(pair<int, int>(0, -1));
pos.push_back(pair<int, int>(-1, 0));
while (!forBFS.empty()) {
Box now = forBFS.top();
forBFS.pop();
if (seaRevel < now.height)
seaRevel = now.height;
for (int i = 0; i < 4; i++) {
pair<int, int> next = pos[i];
int nextX = now.x + next.first;
int nextY = now.y + next.second;
if (nextX < 0 || nextY < 0)
continue;
if (nextX >= rowCount || nextY >= colCount)
continue;
if (!visited[nextX][nextY]) {
water = seaRevel > heightMap[nextX][nextY] ? water + (seaRevel - heightMap[nextX][nextY]) : water + 0;
forBFS.push(Box(nextX, nextY, heightMap[nextX][nextY]));
visited[nextX][nextY] = true;
}
}
}
return water;
}
};
感触:
1、优先队列的使用
2、vector的初始化方法,vector(numberOfElements,value),省去了memset的调用
3、bfs的应用(我觉得也是这道题的难点)
879

被折叠的 条评论
为什么被折叠?



