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;
    }
    
    
  • 相关阅读:
    生产者-消费者模式
    Java中数字操作
    Java中的装箱拆箱
    Java中的匿名类
    JAVA中抽象类的一些总结
    JAVA继承时this和super关键字
    elasticsearch查询
    elasticsearch的映射
    kibana——es的批量操作
    kibana简单使用——elaticsearch的文档,索引的CRUD操作
  • 原文地址:https://www.cnblogs.com/Lour688/p/13415262.html
Copyright © 2011-2022 走看看