1. 程式人生 > >codevs 3634 積水 優先佇列

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;
}