Loading

POJ 2227 The Wedding Juicer(三维接雨水 BFS 贪心

POJ 2227 The Wedding Juicer(三维接雨水 BFS 贪心)

题意:

​ 给出一个二维地图,其各点上权值为其高度。如果向其中填水,请问在这张地图中可以积得多少水。

​ 地图长宽为300,高度最高为1e9。

999							
919										
989 以此图为例,可积水7		

思路:

​ 通过观察所给样例,可以发现,整个地图的储水量取决于最外围的最矮的点。若这个最矮的点被其周围比其高的点挡住,那边界就从这个最矮的点变成了其周围最矮的点。若最矮的点周围还有更矮的点,那他可以积的水为这两点的差值,同样更新一下边界。

​ 那么我们程序化这个过程,将最外一圈放入小根堆中,然后BFS扩展,根据两种情况来更新我们的边界,同时累积水。因为最矮的点是积水的短板,所以每次优先处理它。

实现:

​ 防重走,还有很坑爹的n和m是反的。

int n, m;
int a[305][305];
long long res = 0;
int d[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int vis[305][305];

struct node {
    int x, y, val;
    node(int x_, int y_, int _val) {x = x_, y = y_, val = _val;}
    bool operator < (const node &a) const {
        return val > a.val;
    }
};

int main()
{
    scanf("%d%d", &m, &n);
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= m; j ++)
            scanf("%d", &a[i][j]);
    
    priority_queue<node> q;
    for(int i = 1; i <= n; i ++)
    {
        vis[i][1] = vis[i][m] = 1;
        q.push(node(i, 1, a[i][1]));
        q.push(node(i, m, a[i][m]));
    }
    for(int i = 2; i <= m - 1; i ++)
    {
        vis[1][i] = vis[n][i] = 1;
        q.push(node(1, i, a[1][i]));
        q.push(node(n, i, a[n][i]));
    }

    while(q.size())
    {
        node tmp = q.top();
        q.pop();

        for(int i = 0; i < 4; i ++)
        {
            int xx = tmp.x + d[i][0], yy = tmp.y + d[i][1];
            if(vis[xx][yy]) continue;
            if(xx > n || xx < 1 || yy > m || yy < 1)    continue;
            if(a[xx][yy] >= tmp.val)
                q.push(node(xx, yy, a[xx][yy]));
            else
                q.push(node(xx, yy, tmp.val)), res += (tmp.val - a[xx][yy]);
            vis[xx][yy] = 1;
        }
    }
    printf("%lld\n", res);
}
posted @ 2022-10-05 21:52  DM11  阅读(117)  评论(0编辑  收藏  举报