题目描述 Description
有这样一块土地,它可以被划分N*M个正方形小块,每块面积是一平方英寸,第i行第j列的小块可以表示成P(i,j)。这块土地高低不平,每一小块地P(i,j)都有自己的高度H(i,j)(单位是英寸)。
一场倾盆大雨后,由于这块地地势高低不同,许多低洼地方都积存了不少降水。假如你已经知道这块土地的详细信息,你能求出它最多能积存多少立方英寸的降水么?
输入描述 Input Description
输入文件的第一行是两个正整数n和m,1<=n<=100,1<=m<=100,表示土地的尺寸。下面n行,每行m个整数(1…10000);第j行第i个数表示第j行第i列立方体的高。
输出描述 Output Description
输出文件只有一个数,表示在这个建筑上可以聚合的积水的最大值
样例输入 Sample Input
3 6
3 3 4 4 4 2
3 1 3 2 1 4
7 3 1 6 4 1
样例输出 Sample Output
5
这题要记住,外界是不能存水的,所以边界的水一定会流出去。根据这个性质—木桶效应,水会在边界的最低处流出去,所以整个池的最高高度就是最低的边界。然后水从最低的边界流进去,遇到比自己更低的就更新高度,且加入队列,否则就直接加入队列啥都不干。因为每次我们都首先取最低的高度,所以水会不断的更新方格,当元素取到高于最低边界的格子的时候,周围的比它低的格子已经全部被更新完了,所以这样做答案肯定是对的。因为每次抽取最低积水格子,所以队列我们用优先队列。
第一次写flood fill,感觉良好
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cstring>
#define front top
using namespace std;
struct node
{
int x,y,gao;
bool operator <(const node &vv)const
{
return vv.gao<gao;
}
};
priority_queue<node>q;
int n,m;
int h[105][105],a[105][105],ans;
bool vis[105][105];
const int dx[]={0,0,0,-1,1};
const int dy[]={0,1,-1,0,0};
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int 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]=true;
q.push((node){i,j,h[i][j]});
}
}
}
while(!q.empty())
{
int xx=q.front().x;
int yy=q.front().y;
int anss=q.front().gao;
q.pop();
for(int i=1;i<=4;i++)
{
if(xx+dx[i]>=1&&xx+dx[i]<=n&&yy+dy[i]>=1&&yy+dy[i]<=m&&!vis[xx+dx[i]][yy+dy[i]])
{
if(h[xx][yy]>h[xx+dx[i]][yy+dy[i]])
{
h[xx+dx[i]][yy+dy[i]]=h[xx][yy];
}
vis[xx+dx[i]][yy+dy[i]]=true;
q.push((node){xx+dx[i],yy+dy[i],h[xx+dx[i]][yy+dy[i]]});
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
ans+=h[i][j]-a[i][j];
}
}
cout<<ans;
}