Given n * m non-negative integers representing an elevation map 2d where the area of each cell is 1 * 1, compute how much water it is able to trap after raining.
给出 n * m
个非负整数,代表一张X轴上每个区域为 1 * 1
的 2d 海拔图, 计算这个海拔图最多能接住多少(面积)雨水。
该题解题思路与现实生活完全一致,也就是水往地处流,因此可以通过最小堆及BFS搜索来求解该题。
首先对矩阵数据建堆,
然后从堆里面选取最小元素,进行BSF遍历,如果值相等,继续往下走,如果遇到比当前值小的,或者边境,说明该水流会流出去(遇到这种情况对遍历的数据置为-1)说明往后连通该区域的水都会流出去,如果BFS一遍发现没有到边界和遇到比起小的点,则将遍历过的点的值设为遇到的最小的点,并更新水的流量,继续进行遍历。直至所有点都为-1为止,输出结果
//
// main.cpp
// ContainWalter
//
// Created by 孟文斌 on 15/4/28.
// Copyright (c) 2015年 孟文斌. All rights reserved.
//
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
struct pos{
int x;
int y;
int val;
pos(){}
pos(int a,int b,int c):x(a),y(b),val(c){}
int compare(const void * a, const void *b){
int *ta = (int *)a;
int *tb = (int *)b;
return (*ta - *tb);
}
};
struct ValCmp{
bool operator() (const pos &A,const pos &B){
return A.val > B.val;
}
};
class Solution {
private:
void displayVector(vector<vector<int> > &heights){
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
cout << heights[i][j]<<" ";
}
cout<<endl;
}
}
int m,n;
int visitPos(vector<vector<int>> &heights,pos p){
queue<pos> q,t;
pos tmp;
bool avail = 1;
q.push(p);
heights[p.x][p.y] = -2;
int x,y,v,minn=INT_MAX;
while(!q.empty()){
tmp = q.front();
t.push(tmp);
q.pop();
x = tmp.x;y=tmp.y;
if(x > 0){
v = heights[x-1][y];
if(v == -2){
}else if(v < p.val){
avail = 0;
}else if(v == p.val){
if(avail){
q.push(pos(x-1,y,v));
heights[x-1][y] = -2;
}else {
heights[x-1][y] = -1;
}
}else {
if(avail) minn = min(minn,v);
}
}else {
avail = 0;
}
if(x < m-1){
v = heights[x+1][y];
if(v == -2){
}else if(v < p.val){
avail = 0;
}else if(v == p.val){
if(avail){
q.push(pos(x+1,y,v));
heights[x+1][y] = -2;
}else {
heights[x+1][y] = -1;
}
}else {
if(avail) minn = min(minn,v);
}
}else {
avail = 0;
}
if(y > 0){
v = heights[x][y-1];
if(v == -2){
}else if(v < p.val){
avail = 0;
}else if(v == p.val){
if(avail){
q.push(pos(x,y-1,v));
heights[x][y-1] = -2;
}else {
heights[x][y-1] = -1;
}
}else {
if(avail) minn = min(minn,v);
}
}else {
avail = 0;
}
if(y < n-1){
v = heights[x][y+1];
if(v == -2){
}else if(v < p.val){
avail = 0;
}else if(v == p.val){
if(avail){
q.push(pos(x,y+1,v));
heights[x][y+1] = -2;
}else {
heights[x][y+1] = -1;
}
}else {
if(avail) minn = min(minn,v);
}
}else {
avail = 0;
}
}
if(avail){
int val = 0;
while (!t.empty()) {
tmp = t.front();
t.pop();
x = tmp.x;y=tmp.y;
heights[x][y] = minn;
val += minn-p.val;
}
return val;
}
while (!t.empty()) {
tmp = t.front();
t.pop();
heights[tmp.x][tmp.y] = -1;
}
return 0;
}
public:
/**
* @param heights: a matrix of integers
* @return: an integer
*/
int trapRainWater(vector<vector<int> > &heights) {
// write your code here
m = (int)heights.size();
if(!m) return 0;
n = (int)heights[0].size();
priority_queue<pos,vector<pos,allocator<pos>>,ValCmp> hights_heap;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
hights_heap.push(pos(i,j,heights[i][j]));
}
}
int val = 0,tv;
while (!hights_heap.empty()) {
pos p = hights_heap.top();
hights_heap.pop();
if(heights[p.x][p.y] != p.val) continue;//current point is visited before
tv = visitPos(heights,p);
if(tv){
val += tv;
p.val = heights[p.x][p.y];
hights_heap.push(p);
}
}
return val;
}
};
int main(int argc, const char * argv[]) {
// vector<vector<int> > heights = {{12,13,0,12},{13,4,13,12},{13,8,10,12},{12,13,12,12},{13,13,13,13}};
// vector<vector<int> > heights = {{25,10,11,12,13},{24,9,2,3,14},{23,8,1,4,15},{22,7,6,5,16},{21,20,19,18,17}};
vector<vector<int> > heights = {
{25,10, 9,12,13},
{24, 4, 5, 3,14},
{23, 8, 3, 4,15},
{22, 6, 9, 5,16},
{21,20, 0,18,17}};
Solution sol;
cout<<sol.trapRainWater(heights)<<endl;
return 0;
}