积水问题。
题目:http://main.edu.pl/en/archive/oi/6/wod
题意:一个凹凸不平的池塘,每一个块儿高度不同,因而下雨后由于相邻的高度落差会有积水。问:这个池塘最多积水多少。
我们可以用一个最小堆来维护当前堆里高度的最小值。
边界的块儿不可能积水,全部边界点入队列。然后Pop一个点开始Floodfill,寻找比他高度小的,这样的块儿会有积水。积水的多少位高度差,比他高度大的入队列。继续对堆里的点Floodfill。
对于堆的维护,直接用S TL优先队列即可。自己手敲也可以。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <stack>
#include <queue>
using namespace std;
struct Point
{
int x,y;
int h;
Point()
{
}
Point(int x1,int y1,int h1)
{
x = x1;
y = y1;
h = h1;
}
};
int n,m;
int map[105][105];
int vis[105][105];
int disx[4] = {-1,0,1,0};
int disy[4] = {0,1,0,-1};
int total = 0;
//定义比较结构
struct cmp
{
bool operator ()(Point &a,Point &b)
{
return a.h>b.h;
}
};
priority_queue<Point,vector<Point>,cmp> p;
void floodfill(int x,int y,int h)
{
for(int i=0;i<4;i++)
{
int tempx = x + disx[i];
int tempy = y + disy[i];
if(tempx>=1 && tempx<=n && tempy>=1 && tempy<=m && vis[tempx][tempy] == 0)
{
vis[tempx][tempy] = 1;
if(map[tempx][tempy] >= h)
{
Point t;
t.x = tempx,t.y = tempy,t.h = map[tempx][tempy];
p.push(t);
}
else
{
total = total + (h - map[tempx][tempy]);
floodfill(tempx,tempy,h);
}
}
}
}
int main()
{
/*#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif*/
while(scanf(" %d %d",&n,&m)!=EOF)
{
memset(map,0,sizeof(map));
memset(vis,0,sizeof(vis));
total = 0;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
scanf(" %d",&map[i][j]);
}
}
//清空最小堆
while(!p.empty()) p.pop();
for(int i=1;i<=n;i++)
{
Point t1(i,1,map[i][1]),t2(i,m,map[i][m]);
if(m == 1)
{
p.push(t1);
}
else
{
p.push(t1),p.push(t2);
}
vis[t1.x][t1.y] = 1;
vis[t2.x][t2.y] = 1;
}
for(int j=2;j<=m-1;j++)
{
Point t1(1,j,map[1][j]),t2(n,j,map[n][j]);
if(n == 1)
{
p.push(t1);
}
else
{
p.push(t1),p.push(t2);
}
vis[t1.x][t1.y] = 1;
vis[t2.x][t2.y] = 1;
}
while(!p.empty())
{
Point temp;
temp = p.top();
p.pop();
floodfill(temp.x,temp.y,map[temp.x][temp.y]);
}
printf("%d",total);
}
return 0;
}