codevs 3634 積水 優先佇列
阿新 • • 發佈:2018-11-03
題目描述 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; }