codevs 3634 积水 优先队列

题目描述 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;
}

猜你喜欢

转载自blog.csdn.net/qq_37073764/article/details/83540827