题目大意:给出一幅海洋的描述,0为海平面,负数即有水,在给出的xy坐标的底部安放抽水机,问最多能有多少水。水往低处流,且八个方向都可以。
思路:bfs,记录到每一个节点有效的最低海平面,然后尝试更新周围的点。
但这道题需要优先队列,有效海平面最低的先出队,否则会TLE。
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<string.h> #include<sstream> #include<set> #include<map> #include<vector> #include<queue> #include<stack> #include<bitset> #define CLR(a,b) memset((a),(b),sizeof((a))) using namespace std; typedef long long ll; inline int rd() { int f = 1; int x = 0; char s = getchar(); while (s<'0' || s>'9') { if (s == '-')f = -1; s = getchar(); } while (s >= '0'&&s <= '9') { x = x * 10 + s - '0'; s = getchar(); }x *= f; return x; } const int maxn = 510; ll mp[maxn][maxn],mmp[maxn][maxn],vis[maxn][maxn]; int n, m, x, y; int fx[8][2] = { {-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0} }; struct dian { int x, y; ll low; inline dian(){} inline dian(int x,int y,ll low):x(x),y(y),low(low){} inline friend bool operator <(const dian & a, const dian &b) { return a.low > b.low; } }; inline bool check(dian &s) { if (s.x <= 0 || s.y <= 0 || s.x > n || s.y > m||vis[s.x][s.y])return false; if (mp[s.x][s.y] > 0)return false; return true; } priority_queue<dian >q; int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { scanf("%I64d", &mp[i][j]); } } scanf("%d%d", &x, &y); if (mp[x][y] > 0) { printf("0 "); return 0; } q.push(dian(x, y,mp[x][y])); ll ans =0; mmp[x][y] = mp[x][y]; vis[x][y] = 1; while (!q. empty()) { dian st = q.top(); q.pop(); for (int i = 0; i < 8; i++) { dian now = st; now.x += fx[i][0], now.y += fx[i][1]; if (!check(now))continue; now.low= -min(-st.low, -mp[now.x][now.y]); if (now.low < mmp[now.x][now.y]) { q.push(now); mmp[now.x][now.y] = now.low; vis[now.x][now.y] = 1; } } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { ans -= mmp[i][j]; } } printf("%I64d ", ans); }