1687:积水问题
时间限制: 1000 ms 内存限制: 262144 KB
【题目描述】
有一块矩形土地被划分成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%的数据,n,m≤4。
对于40%的数据,n,m≤15。
对于60%的数据,n,m≤50。
对于100%的数据,n,m≤300,|小块高度|≤109。
在每一部分数据中,均有一半数据保证小块高度非负。
代码
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int N = 386;
int G[N][N];
const int dx[] = {1, -1, 0, 0};
const int dy[] = {0, 0, 1, -1};
int f[N * N];
int n, m;
int get(int u)
{
if (f[u] == u)
return u;
else
return f[u] = get(f[u]);
}
void merge(int a, int b)
{
int fa = get(a);
int fb = get(b);
if (fa != fb)
f[fa] = fb;
}
struct node
{
int x, y;
inline bool operator<(const node &a) const
{
return G[x][y] < G[a.x][a.y];
}
} map_list[N * N];
int pos[N][N];
bool vis[N][N];
bool tag[N * N]; //流到边界
void bfs(int sx, int sy)
{
queue<node> Q;
Q.push(node({sx, sy}));
vis[sx][sy] = true;
int sp = pos[sx][sy];
vector<node> L;
while (!Q.empty())
{
L.push_back(Q.front());
int ux = Q.front().x;
int uy = Q.front().y;
Q.pop();
for (int i = 0; i < 4; i++)
{
int vx = ux + dx[i];
int vy = uy + dy[i];
if (vx > 0 && vx <= n && vy > 0 && vy <= m)
{
if (G[vx][vy] < G[ux][uy] && tag[get(pos[vx][vy])])
tag[get(sp)] = true;
if (vis[vx][vy] || G[vx][vy] != G[ux][uy])
continue;
Q.push(node({vx, vy}));
vis[vx][vy] = true;
merge(pos[vx][vy], sp);
}
}
}
for (auto i : L)
{
int ux = i.x;
int uy = i.y;
for (int j = 0; j < 4; j++)
{
int vx = ux + dx[j];
int vy = uy + dy[j];
if (vx > 0 && vx <= n && vy > 0 && vy <= m && vis[vx][vy])
{
if (G[ux][uy] > G[vx][vy] && !tag[get(pos[vx][vy])])
merge(pos[vx][vy], sp);
}
}
}
}
int idx[N * N][2];
int main()
{
cin >> n >> m;
n += 2;
m += 2;
int tot = 0;
for (int i = 2; i < n; i++)
for (int j = 2; j < m; j++)
{
cin >> G[i][j];
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
map_list[++tot] = {i, j};
f[tot] = tot;
idx[tot][0] = i;
idx[tot][1] = j;
pos[i][j] = tot;
if (i == 1 || i == n || j == 1 || j == m)
tag[tot] = true;
}
sort(map_list + 1, map_list + tot + 1);
for (int i = 1; i <= tot; i++)
{
if (!vis[map_list[i].x][map_list[i].y])
bfs(map_list[i].x, map_list[i].y);
}
for (int i = 2; i < n; i++)
{
for (int j = 2; j < m; j++)
{
int p = get(pos[i][j]);
cout << G[idx[p][0]][idx[p][1]] - G[i][j] << ' ';
}
cout << endl;
}
return 0;
}
|