1. 程式人生 > >搜索-幻象迷宮(洛谷P1363)

搜索-幻象迷宮(洛谷P1363)

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)