CF1422D
首先联想到最短路,
以每个转折点为顶点,两两连一条边,再加上起点与终点,就可以了。
但这样边数至少有 $O(m^2)$,会爆炸,
考虑优化:我们直连一个点与它上下左右相邻最近的点就行了,
举个例子:
有三个转折点:$A(1, 2)$,$B (3, 3)$,$C (4, 7)$,要从 $A$ 走到 $C$,
-
直接走:花费 $3$ 的代价
-
先走 $B$,在走 $C$,花费 $2 + 1 = 3$ 的代价
两种走法一样,就可以不连 $AC$ 这条边。
而 $B$ 更接近于 $A$。
四个方向,有 $O (4m)$ 条边,加上起点与终点,共 $O(6m + 1)$ 条边,
最短路大家都很熟,这里不讲了。
#include <queue>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define int long long
const int N = 1e5 + 10;
const int inf = (1 << 30);
struct node {
int x, y, id;
} t[N];
struct Node {
int w, to, nxt;
} edge[N << 3];
int cnt, head[N];
int n, m;
int sx, sy, tx, ty;
int dis[N];
bool vis[N];
priority_queue <pair <int, int> > q;
bool cmpx (node p, node q) {
return p.x < q.x;
}
bool cmpy (node p, node q) {
return p.y < q.y;
}
void add (int u, int v, int w) {
cnt ++;
edge[cnt].w = w;
edge[cnt].to = v;
edge[cnt].nxt = head[u];
head[u] = cnt;
}
void dij () { // 最短路
memset (dis, 0x7f, sizeof (dis));
dis[0] = 0;
q.push (make_pair (0, 0));
while (!q.empty()) {
int u = q.top().second; int d = -q.top().first; q.pop(); // 由于是大根堆,所以取负的存,使得小的先
if (vis[u]) continue;
vis[u] = 1;
for (int i = head[u]; i; i = edge[i].nxt) {
int v = edge[i].to, w = edge[i].w;
if (dis[v] > d + w) {
dis[v] = d + w;
q.push (make_pair (-dis[v], v));
}
}
}
printf ("%d", dis[m + 1]);
}
int main() {
scanf ("%d%d", &n, &m);
scanf ("%d%d%d%d", &sx, &sy, &tx, &ty);
for (int i = 1; i <= m; ++i) {
scanf ("%d%d", &t[i].x, &t[i].y); t[i].id = i;
}
sort (t + 1, t + m + 1, cmpx); // 按照 x 轴排序,保证在 x 轴情况下,最接近
for (int i = 1; i <= m - 1; ++i) {
add (t[i].id, t[i + 1].id, t[i + 1].x - t[i].x);
add (t[i + 1].id, t[i].id, t[i + 1].x - t[i].x);
}
sort (t + 1, t + m + 1, cmpy); // 同上,按 y 轴排序
for (int i = 1; i <= m - 1; ++i) {
add (t[i].id, t[i + 1].id, t[i + 1].y - t[i].y);
add (t[i + 1].id, t[i].id, t[i + 1].y - t[i].y);
}
for (int i = 1; i <= m; ++i) {
add (0, t[i].id, min (abs (sx - t[i].x), abs (sy - t[i].y)));
add (t[i].id, m + 1, abs (tx - t[i].x) + abs (ty - t[i].y));
}
add (0, m + 1, abs (sx - tx) + abs (sy - ty));
dij ();
return 0;
}
浙公网安备 33010602011771号