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

考试的时候想了 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;
} 

猜你喜欢

转载自www.cnblogs.com/ghcred/p/9750274.html
今日推荐