[bfs][堆] Jzoj P5830 water
题解
- 首先,我们可以先将周围一圈的先加入小根堆,对于负数的,先将其定为0
- 然后,bfs每次找到x四周第一个大于它的高度,那么小于它的就是加上h-a[x][y](x和y是当前四周搜到的高度,h为x的高度)
- 以此类推
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <queue> 4 using namespace std; 5 struct edge 6 { 7 int x,y;long long v; 8 bool operator < (const edge &a) const { return v>a.v; } 9 }u; 10 priority_queue <edge> Q; 11 int n,m,visit[310][310],dx[4]={0,0,1,-1},dy[4]={1,-1,0,0},a[310][310],h[310][310]; 12 bool pd(int x,int y) 13 { 14 if (x<1||x>n||y<1||y>m||visit[x][y]==1) return false; 15 return true; 16 } 17 void work(int x,int y,int v) 18 { 19 visit[x][y]=1; 20 if (a[x][y]>v) 21 { 22 Q.push((edge){x,y,a[x][y]}); 23 return; 24 } 25 h[x][y]+=v-a[x][y]; 26 for (int i=0;i<=3;i++) 27 if (pd(x+dx[i],y+dy[i])) 28 work(x+dx[i],y+dy[i],v); 29 } 30 void bfs() 31 { 32 while (!Q.empty()) 33 { 34 u=Q.top(),Q.pop(); 35 for (int i=0;i<=3;i++) 36 if (pd(u.x+dx[i],u.y+dy[i])) 37 work(u.x+dx[i],u.y+dy[i],u.v); 38 } 39 } 40 int main() 41 { 42 //freopen("water.in","r",stdin); 43 //freopen("water.out","w",stdout); 44 scanf("%d%d",&n,&m); 45 for (int i=1;i<=n;i++) 46 for (int j=1;j<=m;j++) 47 { 48 scanf("%d",&a[i][j]); 49 if (a[i][j]<0) h[i][j]=-a[i][j],a[i][j]=0; 50 if (i==1||j==1||i==n||j==m) Q.push((edge){i,j,a[i][j]}),visit[i][j]=1; 51 } 52 bfs(); 53 for (int i=1;i<=n;i++) 54 { 55 for (int j=1;j<=m;j++) printf("%d ",h[i][j]); 56 printf("\n"); 57 } 58 return 0; 59 }