題目大意:
給出一個的矩陣,由 組成
表示空地
表示牆(保證圖的四邊爲牆)
各表示一個人
C要走到F那個格子,C有兩種移動方式:
1.往上下左右任意方向移動一格(不能爲牆) 耗時爲1
2.在相鄰的牆放一個傳送門,可以往四周最近的牆放一道傳送門(可以不相鄰,面向C,放傳送門不耗時間),整個圖最多存在兩個傳送門,如果多於三道則最先放的一道門會消失,然後通過傳送門移動耗時爲1
解題思路:
C、F先記錄位置然後當做空地
廣搜找任意一個空地與距離這個點最近的牆之間的距離
然後建邊跑一遍最短路就可以了
#include<queue>
#include<cstdio>
#include<cstring>
#define g(x, y) (node){x, y}
#define id(x, y) (((x)-1) * m + (y))
using namespace std;
const int N = 505;
const int inf = 1e9;
struct node {
int x, y;
};
struct line {
int to, z, next;
}e[N*N<<3];
int n, m, s, t, cnt;
int v[N*N], dis[N*N], len[N][N], last[N*N<<3];
int up[N][N], left[N][N], down[N][N], right[N][N];
char a[N][N];
queue <node> q;
void check(int x, int y, int L) {
if (a[x][y] == '.' && !len[x][y])
len[x][y] = L, q.push(g(x, y));
}
void bfs() {
while (q.size()) {
int x = q.front().x;
int y = q.front().y;
q.pop();
check(x - 1, y, len[x][y] + 1);
check(x, y - 1, len[x][y] + 1);
check(x + 1, y, len[x][y] + 1);
check(x, y + 1, len[x][y] + 1);
}
}
void find() {
for (int i = 1, i1 = n; i <= n; ++i, --i1)
for (int j = 1, j1 = m; j <= m; ++j, --j1) {
if (a[i][j] == '.') {
if (a[i-1][j] == '#') //上
up[i][j] = id(i, j);
else up[i][j] = up[i-1][j];
if (a[i][j-1] == '#') //左
left[i][j] = id(i, j);
else left[i][j] = left[i][j-1];
}
if (a[i1][j1] == '.') {
if (a[i1+1][j1] == '#') //下
down[i1][j1] = id(i1, j1);
else down[i1][j1] = down[i1+1][j1];
if (a[i1][j1+1] == '#') //右
right[i1][j1] = id(i1, j1);
else right[i1][j1] = right[i1][j1+1];
}
}
}
void add(int x, int y, int w) {
e[++cnt] = (line){y, w, last[x]}; last[x] = cnt;
}
void addL(int x, int y, int w) {
add(x, y, w); add(y, x, w);
}
void addline() {
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
if (a[i][j] == '.') {
if (a[i][j+1] == '.') addL(id(i, j), id(i, j+1), 1);
if (a[i+1][j] == '.') addL(id(i, j), id(i+1, j), 1);
if (up[i][j] != id(i, j)) add(id(i, j), up[i][j], len[i][j]);
if (down[i][j] != id(i, j)) add(id(i, j), down[i][j], len[i][j]);
if (left[i][j] != id(i, j)) add(id(i, j), left[i][j], len[i][j]);
if (right[i][j] != id(i, j)) add(id(i, j), right[i][j], len[i][j]);
}
}
void Spfa() {
memset(dis, 127 / 3, sizeof dis);
memset(v, 0, sizeof v);
dis[s] = 0; v[s] = 1;
queue <int> que;
que.push(s);
while (que.size()) {
int x = que.front(); v[x] = 0; que.pop();
for (int i = last[x]; i; i = e[i].next) {
int y = e[i].to;
if (dis[y] > dis[x] + e[i].z) {
dis[y] = dis[x] + e[i].z;
if (!v[y]) {
que.push(y);
v[y] = 1;
}
}
}
}
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++i)
scanf("%s", a[i] + 1);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j) {
if (a[i][j] == 'C') s = id(i, j), a[i][j] = '.';
if (a[i][j] == 'F') t = id(i, j), a[i][j] = '.';
}
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
if (a[i][j] == '#') q.push(g(i, j));
bfs(), find(), addline(), Spfa();
if (dis[t] >= inf) puts("no"); else printf("%d", dis[t]);
}