搜索-幻象迷宮(洛谷P1363)
阿新 • • 發佈:2018-10-07
spa tarjan 出發 con 一個 nod can tdi bool
考試的時候想了 Tarjan 和 Topsort ,發覺不對,改寫玄學貪心:算 S 出發可以穿梭到達的點,以及原圖上可以互相到達的點。枚舉兩個邊界上相鄰位置的點(比如 (x, 1) 和 (x, m) ),如果能被 S 穿梭到達,且兩者可以直接到達(用並查集維護 Orz ),就是可行方案。不過顯然有反例,因為兩者之間也可以穿梭到達,不過不能與 S 到他們的路線重合……
這樣想就非常惡心。
直接搜索四周,記錄下到達相對位置 (x, y) 的實際坐標(可以是一個負數或者巨大的數)。如果能到達某個相同的相對做標的,是兩個不同的實際坐標,那麽是有可行方案的。
題不難,寫一發題解是因為這題算上考試時做的時間,我總共做了三個小時 OrzOrz 。
#include <cstdio> #include <algorithm> #include <queue> #include <ctype.h> using namespace std; const int INF = 1e9; struct node { int x, y; node(int x = 0, int y = 0) : x(x), y(y) { } }; queue<node> Q; int N, M; char G[1550][1550]; int nxt[4][2] = {0,1,0,-1,1,0,-1,0}; int mk_x[1550][1550], mk_y[1550][1550]; int mm(int v, int m) { int t = (v % m + m) % m; return t ? t : m; } bool bfs(node bg) { for (int i = 1; i <= N; ++i) for (int j = 1; j <= M; ++j) mk_x[i][j] = mk_y[i][j] = INF; mk_x[bg.x][bg.y] = bg.x, mk_y[bg.x][bg.y] = bg.y; while (!Q.empty()) Q.pop(); Q.push(bg); while (!Q.empty()) { node p = Q.front(); Q.pop(); for (int i = 0; i < 4; ++i) { int tx = p.x + nxt[i][0], ty = p.y + nxt[i][1]; int gx = mm(tx, N), gy = mm(ty, M); if (G[gx][gy] == '#' || mk_x[gx][gy] == tx && mk_y[gx][gy] == ty) continue; if (mk_x[gx][gy] == INF && mk_x[gx][gy] == INF) { Q.push(node(tx, ty)); mk_x[gx][gy] = tx, mk_y[gx][gy] = ty; } else { return true; } } } return false; } int main() { while (scanf("%d%d", &N, &M) == 2) { node bg; for (int i = 1; i <= N; ++i) { char tt; while ((tt = getchar()) != '#' && tt != '.' && tt != 'S'); G[i][1] = tt; if (G[i][1] == 'S') bg = node(i, 1); for (int j = 2; j <= M; ++j) { G[i][j] = getchar(); if (G[i][j] == 'S') bg = node(i, j); } } if (bfs(bg)) printf("Yes\n"); else printf("No\n"); } return 0; }
搜索-幻象迷宮(洛谷P1363)