题意:n*m的地图, 每个格子有一个海拔高度, 海拔<0的地方有水, 现在在(x, y)最深处放一个抽水机, 问最多能抽多少水, 水只能从高处往低处流。(n, m <= 500)
思路:从(x,y)开始bfs,扩展到的点v[tu][tv] = max(v[tu][tv], v[u][v])。但是不能用普通的bfs。需要加优先队列。(点
击打开链接)因为水可以往八个方向流, 如果先出队列的不出最深的一个点的话, 原本能流过去的水可能就流不过去
了, 所以用优先队列, 保证先出队列的是当前已处理的最深的节点。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e3+5;
int v[maxn][maxn], n, m, x, y;
bool vis[maxn][maxn];
struct node
{
int x, y;
node() {}
node(int xx, int yy):x(xx), y(yy) {}
bool operator <(const node &a) const
{
return v[x][y] > v[a.x][a.y];
}
};
void bfs()
{
priority_queue<node> pq;
pq.push(node(x, y));
vis[x][y] = 1;
while(!pq.empty())
{
node u = pq.top(); pq.pop();
int next[8][2] = {0, 1, 0, -1, 1, 0, -1, 0, 1, 1, 1, -1, -1, 1, -1, -1};
for(int i = 0; i < 8; i++)
{
int tx = u.x+next[i][0];
int ty = u.y+next[i][1];
if(tx >= 1 && tx <= n && ty >= 1 && ty <= m && !vis[tx][ty])
{
vis[tx][ty] = 1;
v[tx][ty] = max(v[tx][ty], v[u.x][u.y]);
pq.push(node(tx, ty));
}
}
}
}
int main(void)
{
while(cin >> n >> m)
{
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
scanf("%d", &v[i][j]);
x, y;
scanf("%d%d", &x, &y);
bfs();
ll ans = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
if(v[i][j] < 0)
ans += -v[i][j];
printf("%lld\n", ans);
}
return 0;
}