2936: [Poi1999]降 水
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 61 Solved: 41
[ Submit][ Status][ Discuss]
Description
有这样一块土地,它可以被划分成N×M个正方形小块,每块面积是一平方英寸,第i行第j列的小块可以表示成P(i,j)。这块土地高低不平,每一小块地P(i,j)都有自己的高度H(i,j)(单位是英寸)。
一场倾盆大雨后,这块地由于地势高低不同,许多低洼地方都积存了不少降水。假如你已经知道这块土地的详细信息,你能求出它最多能积存多少立方英寸的降水么?
Input
输入文件第一行有两个数,N,M(1<=N, M <=100),表示土地的规模是N×M平方英寸。
以下有N行,每行有M个整数,表示每块地的高低(每个整数在[1,10000]内,以英寸为单位)。
Output
输出文件只有一行,一个数,表示土地中最多能积存多少立方英寸的水。
Sample Input
3 6
3 3 4 4 4 2
3 1 3 2 1 4
7 3 1 6 4 1
3 3 4 4 4 2
3 1 3 2 1 4
7 3 1 6 4 1
Sample Output
5
HINT
Source
【题解】【BFS】
【听说这叫floodfill,其实就是BFS,但是为了时间着想,每个点只遍历一次。要做到这点,那么考虑从最小的开始枚举】
【每次枚举到一个点,如果它周围有点的高度比它高,那么把当前点的高度置为当前最高高度。最后,计算每个点与原高度的差值,加和。】
【注,如果边界不能积水】
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{
int hang,line,val;
bool operator <(const node &x)const
{
return x.val<val;
}
};
priority_queue<node>que;
int d[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int a[110][110],h[110][110],n,m,ans;
bool vis[110][110];
int main()
{
int i,j;
scanf("%d%d",&n,&m);
for(i=1;i<=n;++i)
for(j=1;j<=m;++j)
{
scanf("%d",&a[i][j]);
h[i][j]=a[i][j];
if(i==1||i==n||j==1||j==m)
{
vis[i][j]=1;
node d; d.hang=i; d.line=j; d.val=a[i][j];
que.push(d);
}
}
while(!que.empty())
{
node u=que.top(); que.pop();
int x=u.hang,y=u.line,v=u.val;
for(i=0;i<4;++i)
{
int xx=x+d[i][0],yy=y+d[i][1];
if(xx>0&&xx<=n&&yy>0&&yy<=m&&!vis[xx][yy])
{
if(h[xx][yy]<v) h[xx][yy]=v;
node b; b.hang=xx; b.line=yy; b.val=h[xx][yy];
que.push(b); vis[xx][yy]=1;
}
}
}
for(i=1;i<=n;++i)
for(j=1;j<=m;++j)
ans+=(h[i][j]-a[i][j]);
printf("%d\n",ans);
return 0;
}