zoukankan      html  css  js  c++  java
  • Jzoj P5830 water (优先队列BFS)

    Description

    有一块矩形土地被划分成 n*m 个正方形小块。这些小块高低不 平,每一小块都有自己的高度。水流可以由任意一块地流向周围四个 方向的四块地中,但是不能直接流入对角相连的小块中。 一场大雨后,由于地势高低不同,许多地方都积存了不少降水。 给定每个小块的高度,求每个小块的积水高度。 注意:假设矩形地外围无限大且高度为 0。

    Input

    第一行包含两个非负整数 n,m。 接下来 n 行每行 m 个整数表示第 i 行第 j 列的小块的高度。
    Output
    输出 n 行,每行 m 个由空格隔开的非负整数,表示每个小块的积 水高度。

    Sample Input

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

    Sample Output

    0 0 0
    0 1 0
    0 0 1 
    

    Data Constraint

    对于 20%的数据 n,m<=4
    对于 40%的数据 n,m<=15
    对于 60%的数据 n,m<=50
    对于 100%的数据 n,m<=300,|小块高度|<=10^9。
    在每一部分数据中,均有一半数据保证小块高度非负

    Solution

    首先将所有小于0的补为0,将边上一圈作为边界放入堆,然后向内拓展,因为每次都是取最矮的边界,所以是正确的,且每块地只被更新一次
    代码中有注释,或许可以解决一些问题

    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <cmath>
    #include <cstring>
    using namespace std;
    const int maxn=300+5;
    int n,m;
    int h[maxn][maxn];
    int ans[maxn][maxn];
    bool vis[maxn][maxn];
    int dx[]={0,-1,0,0,1};
    int dy[]={0,0,-1,1,0};
    struct Node{
    	int x,y,val;
    	Node(){}
    	Node(int _x,int _y,int _val){
    		x=_x,y=_y,val=_val;
    	}
    	bool operator < (const Node &B)const{
    		return val>B.val;
    	}
    };
    priority_queue <Node> q;
    int main(){
    	//freopen("1.in","r",stdin);
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=m;++j){
    			scanf("%d",&h[i][j]);
    			if(h[i][j]<0) ans[i][j]+=(-h[i][j]),h[i][j]=0; //先填为0,好处理,因为最后至少是0
    			if(i==1||i==n||j==1||j==m) q.push(Node(i,j,h[i][j])),vis[i][j]=1;//将出口入堆
    		}
    	}
    	int x,y,val;
    	while(!q.empty()){
    		x=q.top().x; y=q.top().y; val=q.top().val; q.pop();
    		for(int i=1,rx,ry;i<=4;++i){
    			rx=x+dx[i]; ry=y+dy[i];
    			if(vis[rx][ry] || rx<1 || rx>n || ry<1 || ry>m) continue; //目标点不合法或已搜过
    			if(val>h[rx][ry]) ans[rx][ry]+=(val-h[rx][ry]); //目标点比当前低,累加答案
    			vis[rx][ry]=1;
    			q.push(Node(rx,ry,max(h[rx][ry],val)));// 向内拓展,不用担心取max会使结果错误,因为每次从堆中取的点都是最低的
    		}
    	}
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=m;++j){
    			printf("%d ",ans[i][j]);
    		}
    		printf("
    ");
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    LeetCode 461. Hamming Distance
    LeetCode 442. Find All Duplicates in an Array
    LeetCode 448. Find All Numbers Disappeared in an Array
    LeetCode Find the Difference
    LeetCode 415. Add Strings
    LeetCode 445. Add Two Numbers II
    LeetCode 438. Find All Anagrams in a String
    LeetCode 463. Island Perimeter
    LeetCode 362. Design Hit Counter
    LeetCode 359. Logger Rate Limiter
  • 原文地址:https://www.cnblogs.com/Lour688/p/13415262.html
Copyright © 2011-2022 走看看