1. 程式人生 > 實用技巧 >water(搜尋)

water(搜尋)

water

題目描述

有一塊矩形土地被劃分成n*m個正方形小塊。這些小塊高低不平,每一小塊都有自己的高度。水流可以由任意一塊地流向周圍四個方向的四塊地中,但是不能直接流入對角相連的小塊中。
一場大雨後,由於地勢高低不同,許多地方都積存了不少降水。給定每個小塊的高度,求每個小塊的積水高度。
注意:假設矩形地外圍無限大且高度為0。

輸入格式

第一行包含兩個非負整數n,m。

接下來n 行每行 個m整數表示第 i行第j列的小塊的高度。

輸出格式

輸出n行,每行m個由空格隔開的非負整數,表示每個小塊的積水高度。

樣例

樣例輸入

3 3
4 4 0
2 1 3
3 3 -1

樣例輸出

0 0 0
0 1 0
0 0 1

資料範圍與提示

對於20%的資料


對於40%的資料
對於60%的資料
對於100%的資料 ,|小塊高度| 。
在每一部分資料中,均有一半資料保證小塊高度非負

思路:據題意,找出最外圍一圈小塊若為負,則一定可以積水(因為矩形外邊高度為0,即使旁邊也為負且比它矮,兩個塊也可存水),放入堆中,維護小根堆,一次彈出高度最小的暴搜,若可以存水則標記存水量(注意:存水後要將該塊的高度賦為邊上的塊,因為若高塊將矮塊圍起來,矮塊也能存水

 1 #include<cstdio>
 2 #include<queue>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=300+10;
 6 typedef long long ll;
 7 ll a[maxn][maxn],vis[maxn][maxn],b[maxn][maxn];//vis標記該塊有無入堆
 8 int ans=0,n,m;
 9 struct Node{
10     int x,y,w;
11     Node(){};
12     Node(int
a,int b,int c){ 13 x=a; 14 y=b; 15 w=c; 16 } 17 bool operator<(const Node &a)const{ 18 return w>a.w; 19 } 20 };//過載維護小根堆 21 priority_queue<Node> q; 22 void Init(){ 23 scanf("%d%d",&n,&m); 24 for(int i=1;i<=n;i++){ 25 for(int j=1;j<=m;j++){ 26 scanf("%lld",&a[i][j]); 27 if(i==1||j==1||i==n||j==m){ 28 if(a[i][j]<0&&!b[i][j]){ 29 b[i][j]-=a[i][j]; 0 0 0 30 a[i][j]=0;//注意置為0,不然若圖為 0 -2 -10 若-10未置0,-2就不能存水 31 } 0 0 0 32 if(!vis[i][j])q.push((Node){i,j,a[i][j]}); 33 vis[i][j]=1; 34 } 35 } 36 } 37 } 38 void solve(){ 39 while(!q.empty()){ 40 Node u=q.top(); 41 q.pop(); 42 int x=u.x; 43 int y=u.y; 44 int w=u.w; 45 if(y+1<=m&&!vis[x][y+1]){//右邊 46 if(a[x][y+1]>=w) q.push((Node){x,y+1,a[x][y+1]});//不能寫continue,這樣迴圈就結束了而不是 47 else { //只if語句結束 48 b[x][y+1]+=(w-a[x][y+1]); 49 a[x][y+1]=w; 50 q.push((Node){x,y+1,w}); 51 } 52 vis[x][y+1]=1; 53 } 54 if(x-1>=1&&!vis[x-1][y]){//上邊 55 if(a[x-1][y]>=w) q.push((Node){x-1,y,a[x-1][y]}); 56 else{ 57 b[x-1][y]+=(w-a[x-1][y]); 58 a[x-1][y]=w; 59 q.push((Node){x-1,y,w}); 60 } 61 vis[x-1][y]=1; 62 } 63 if(x+1<=n&&!vis[x+1][y]){//下邊 64 if(a[x+1][y]>=w) q.push((Node){x+1,y,a[x+1][y]}); 65 else{ 66 b[x+1][y]+=(w-a[x+1][y]); 67 a[x+1][y]=w; 68 q.push((Node){x+1,y,w}); 69 } 70 vis[x+1][y]=1; 71 } 72 if(y-1>=1&&!vis[x][y-1]){//左邊 73 if(a[x][y-1]>=w) q.push((Node){x,y-1,a[x][y-1]}); 74 else{ 75 b[x][y-1]+=(w-a[x][y-1]); 76 a[x][y-1]=w; 77 q.push((Node){x,y-1,w}); 78 } 79 vis[x][y-1]=1; 80 } 81 } 82 } 83 void print(){ 84 for(int i=1;i<=n;i++){ 85 for(int j=1;j<=m;j++){ 86 printf("%lld ",b[i][j]); 87 } 88 printf("\n"); 89 } 90 } 91 int main(){ 92 Init(); 93 solve(); 94 print(); 95 return 0; 96 }
View Code