洛谷 P6833 [Cnoi2020]雷雨
阿新 • • 發佈:2020-09-21
思路
沒想到思路真的可以這麼暴力……
可以想到,這題其實就是找一個點滿足這個點到題目要求的三個點的最短路之和最小(剔除重複部分),所以直接用 \(Dijkstra\) 求出三個點到每個點的最短路,然後 \(O(N^2)\) 掃描每個點找出滿足上述條件的點即可。
注意輸入的矩陣第一行是 \(n\) 然後遞減,所以如果是從 \(1\) 開始輸入的需要把題目中 \(1\) 和 \(n\) 替換。
gyh 說這題卡空間,但是我寫的只花了 40MB 啊qwq(然後知道似乎他建圖了我沒建圖)
程式碼
#include <cmath> #include <queue> #include <cstdio> #include <vector> #include <cstring> #include <iostream> #include <algorithm> #define ll long long using namespace std; const int A = 1e3 + 11; const int B = 1e6 + 11; const int mod = 1e9 + 7; const int inf = 0x3f3f3f3f; const int dx[4] = {0, 0, 1, -1}; const int dy[4] = {1, -1, 0, 0}; inline int read() { char c = getchar(); int x = 0, f = 1; for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1; for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48); return x * f; } bool vis[A][A]; int n, m, a, b, c; ll dis[3][A][A], map[A][A]; struct node { int x, y; ll val; bool operator < (const node &b) const { return val > b.val; } }; inline void Dij(int sx, int sy, int tag) { priority_queue <node> Q; memset(dis[tag], inf, sizeof(dis[tag])); memset(vis, 0, sizeof(vis)); dis[tag][sx][sy] = map[sx][sy]; Q.push((node){ sx, sy, dis[tag][sx][sy] }); while (!Q.empty()) { int x = Q.top().x, y = Q.top().y; Q.pop(); if (vis[x][y]) continue; vis[x][y] = 1; for (int i = 0; i < 4; i++) { int bx = x + dx[i], by = y + dy[i]; if (bx > n || bx < 1 || by > m || by < 1) continue; if (dis[tag][bx][by] > dis[tag][x][y] + map[bx][by]) { dis[tag][bx][by] = dis[tag][x][y] + 1ll * map[bx][by]; Q.push((node){ bx, by, dis[tag][bx][by] }); } } } } int main() { n = read(), m = read(), a = read(), b = read(), c = read(); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) map[i][j] = read(); Dij(1, a, 0); Dij(n, b, 1); Dij(n, c, 2); ll ans = 1e18; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { ans = min(ans, dis[0][i][j] + dis[1][i][j] + dis[2][i][j] - 2 * map[i][j]); } cout << ans << '\n'; return 0; }