题意:一个n*m矩形区域,其中每个1*1都是有高度的矩形块,高低起伏,求最多储水量。(边界不能储水)
题解:先将边界装入优先队列中(高度越小越优先),并标记为已访问。看队首元素四周未访问过的点,1、如果该点不比队首低,则将它加入队列,标记为已访问,即它变成了新的边界。2、该点比队首低,意味着该点可以储水,更新res值,同时将它加入队列中,但是它的高度为原队首元素的高度,即以它为边界的点不能超过这个高度,同时将该点标记为已访问。(参考http://www.cnblogs.com/tmeteorj/archive/2012/09/25/2702978.html)
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
#define INF 0x3fffffff
#define clr(s,t) memset(s,t,sizeof(s))
#define N 305
int used[N][N],s[N][N],res,n,m;
int ori[4][2] = {{0,-1},{0,1},{-1,0},{1,0}};
struct node{
int x,y,h;
node(int xx,int yy,int hh):x(xx),y(yy),h(hh){};
bool operator<(const node b)const{
return h>b.h;
}
};
priority_queue<struct node> q;
int check(int x,int y){
return x>=0&&x<n&&y>=0&&y<m&&(!used[x][y]);
}
int main(){
int i,j;
scanf("%d %d",&m,&n);
clr(used, 0);
for(i = 0;i<n;i++)
for(j = 0;j<m;j++){
scanf("%d",&s[i][j]);
if(i==0||i==n-1||j==0||j==m-1){
q.push(node(i,j,s[i][j]));
used[i][j] = 1;
}
}
while(!q.empty()){
node now = q.top();
q.pop();
for(i = 0;i<4;i++){
int xx = now.x+ori[i][0];
int yy = now.y+ori[i][1];
if(check(xx, yy)){
if(s[xx][yy] >= now.h)
q.push(node(xx,yy,s[xx][yy]));
else{
res += now.h-s[xx][yy];
q.push(node(xx,yy,now.h));
}
used[xx][yy] = 1;
}
}
}
printf("%d\n",res);
return 0;
}