给定一个 m x n 的矩阵,其中的值均为正整数,代表二维高度图每个单元的高度,请计算图中形状最多能接多少体积的雨水。
说明:
m 和 n 都是小于110的整数。每一个单位的高度都大于0 且小于 20000。
示例:
给出如下 3x6 的高度图:
[
[1,4,3,1,3,2],
[3,2,1,3,2,4],
[2,3,3,2,3,1]
]
返回 4。
如上图所示,这是下雨前的高度图[[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]] 的状态。
下雨后,雨水将会被存储在这些方块中。总的接雨水量是4。
思路分析:刚开始拿到这道题,一脸懵逼,感觉二维平面的处理比一维线性的处理困难太多了。(下面代码是从评论区翻出来的)
首先我们需要明白,在给的高度图中的四个边界上不可能积水。(最上行、最下行、最左、最右列)
我们构造一个优先队列(维持从小到大的排序顺序(小顶堆)),起始我们将四个边界的点全部放入队列(并标记访问),然后使用广度优先搜索法,一直取出队头,如果遇到了比自己高的且没有访问过的点(上下左右四个方向),放入队列(标记访问),如果比自己低,则填充雨水,并更新原始地图。直到队列为空。
struct Qitem{
int x;
int y;
int h;
Qitem(int _x,int _y,int _h):x(_x),y(_y),h(_h){}
};
struct cmp{
bool operator()(const Qitem& a,const Qitem &b){
return a.h>b.h;
}
};
class Solution {
public:
int trapRainWater(vector<vector<int>>& heightMap) {
priority_queue<Qitem,vector<Qitem>,cmp> Q;//小顶堆
//行数或列数小于3,则无法积水
if(heightMap.size() < 3|| heightMap[0].size() < 3){
return 0;
}
int row = heightMap.size();
int col = heightMap[0].size();
vector<vector<int>> Mark(heightMap.size(),vector<int>(heightMap[0].size()));//mark[x][y]用于标记heightMap[x][y]是否访问过
//将四周的点添加至优先级队列,并做标记Mark
for(int i = 0 ; i <row ; i++){
Q.push(Qitem(i,0,heightMap[i][0]));
Mark[i][0] = 1 ;
Q.push(Qitem(i,col - 1 ,heightMap[i][col - 1]));
Mark[i][col - 1 ] = 1 ;
}
for(int j = 1 ; j <col - 1 ; j++){
Q.push(Qitem(0,j,heightMap[0][j]));
Mark[0][j] = 1 ;
Q.push(Qitem(row - 1 ,j,heightMap[row - 1][j]));
Mark[row - 1][j] = 1 ;
}
//扩展的方向数组(上、下、右、左)四个移动方向
static const int dx[] = {-1,1,0,0};
static const int dy[] = {0,0,1,-1};
//最终积水量
int result = 0;
//广度优先遍历
while(!Q.empty()){
//获取队头信息
int x = Q.top().x;
int y = Q.top().y;
int h = Q.top().h;
Q.pop();
//向四个方向扩展
for(int i = 0 ; i < 4 ;i++){
int newx = x + dx[i];
int newy = y + dy[i];
//如果点超出边界或者已经被标记过,则不会进入队列
if(newx < 0 || newx >= row
|| newy < 0 || newy >=col
|| Mark[newx][newy]){
continue;
}
//当前点的高度高于拓展点时,此时需要填充雨水,
if(h >heightMap[newx][newy] ){
result += h - heightMap[newx][newy];
heightMap[newx][newy] = h;//更新原始地图
}
//放入队列,标记访问
Q.push(Qitem(newx,newy,heightMap[newx][newy]));
Mark[newx][newy] = 1 ;
}
}
return result;
}
};