题目大意:
分析:
对于每个点,
向四个相邻点连边,边权为1
向四个方向最远能走到的点连边,边权为通过其他三个方向的传送门走到这个点的最小值
spfa即可
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <cstring>
#include <algorithm>
#define rep(i, st, ed) for (int i = st; i <= ed; i++)
#define rwp(i, ed, st) for (int i = ed; i >= st; i--)
#define inf 0x7fffffff
#define N 505
using namespace std;
struct Node {
int To, nxt, w;
}e[N*N*8*2];
struct Code {
int up, down, lf, rt;
}C[N][N];
int id[N][N], a[N][N], dis[N*N], ls[N*N], S, T, n, m, cnt;
bool vis[N*N];
queue <int> Q;
void Addedge(int u, int v, int w) {
if (u < 1 || u > n * m || v < 1 || v > n * m || u == v) return;
e[++cnt].To = v, e[cnt].nxt = ls[u], e[cnt].w = w, ls[u] = cnt;
}
void spfa() {
rep(i, 1, n * m) dis[i] = inf;
dis[S] = 0; vis[S] = 1; Q.push(S);
while (Q.size()) {
int u = Q.front(); Q.pop();
for (int i = ls[u]; i; i = e[i].nxt)
if (dis[e[i].To] > dis[u] + e[i].w) {
dis[e[i].To] = dis[u] + e[i].w;
if (!vis[e[i].To]) vis[e[i].To] = 1, Q.push(e[i].To);
}
vis[u] = 0;
}
}
int main() {
freopen("cell.in", "r", stdin);
freopen("cell.out", "w", stdout);
scanf("%d %d", &n, &m);
char ch[N];
rep(i, 1, n) {
scanf("%s", ch + 1);
rep(j, 1, m) {
if (ch[j] != '#') a[i][j] = 1;
id[i][j] = m * (i - 1) + j;
if (ch[j] == 'C') S = id[i][j];
if (ch[j] == 'F') T = id[i][j];
}
}
rep(i, 1, n)
rep(j, 1, m) if (a[i][j]) C[i][j].up = C[i - 1][j].up + 1, C[i][j].lf = C[i][j - 1].lf + 1;
rwp(i, n, 1)
rwp(j, m, 1) if (a[i][j]) C[i][j].down = C[i + 1][j].down + 1, C[i][j].rt = C[i][j + 1].rt + 1;
rep(i, 1, n)
rep(j, 1, m) if (a[i][j]) {
Addedge(id[i][j], id[i - 1][j], 1); Addedge(id[i][j], id[i + 1][j], 1);
Addedge(id[i][j], id[i][j - 1], 1); Addedge(id[i][j], id[i][j + 1], 1);
Addedge(id[i][j], id[i - C[i][j].up + 1][j], min(C[i][j].down, min(C[i][j].lf, C[i][j].rt)));
Addedge(id[i][j], id[i + C[i][j].down - 1][j], min(C[i][j].up, min(C[i][j].lf, C[i][j].rt)));
Addedge(id[i][j], id[i][j - C[i][j].lf + 1], min(C[i][j].rt, min(C[i][j].up, C[i][j].down)));
Addedge(id[i][j], id[i][j + C[i][j].rt - 1], min(C[i][j].lf, min(C[i][j].up, C[i][j].down)));
}
spfa();
if (dis[T] != inf) printf("%d\n", dis[T]); else printf("no\n");
return 0;
}
来源:https://blog.csdn.net/Gx_Man_VIP/article/details/98969539