洛谷 P6833 [Cnoi2020]雷雨
思路
没想到思路真的可以这么暴力……
可以想到,这题其实就是找一个点满足这个点到题目要求的三个点的最短路之和最小(剔除重复部分),所以直接用 \(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;
}
转载不必联系作者,但请声明出处