1 条题解

  • 0
    @ 2025-3-22 15:09:16
    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 250;
    const int MAXQ = 100000;
    const int MAXTOT = 250 * 4 + 250 * 4;
    int n, m, Q;
    int dx[] = {0, 0, -1, 1};
    int dy[] = {-1, 1, 0, 0};
    bool g[MAXN + 5][MAXN + 5];
    // 每个点上下左右能到的位置
    pair<int, int> nxt[MAXN + 5][MAXN + 5][4];
    // 有效点
    int tot, idx[MAXN + 5][MAXN + 5];
    pair<int, int> p[MAXTOT + 5];
    // 每对有效点之间的图 tot * tot
    vector<pair<int, int>> e[MAXTOT + 5][MAXTOT + 5];
    queue<pair<int, int>> q;
    int dis[MAXTOT + 5][MAXTOT + 5];
    bool vis[MAXTOT + 5][MAXTOT + 5];
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin >> n >> m >> Q;
        for (int i = 0; i <= n + 1; i++)
            g[0][i] = g[i][0] = g[n + 1][i] = g[i][n + 1] = true;
        for (int i = 1; i <= m; i++)
        {
            int x, y;
            cin >> x >> y;
            g[x][y] = true;
        }
        // 预处理每个点上下左右能到的位置,可以优化,但是不优化也能过
        // 为了可读性,就不优化了
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
            {
                if (g[i][j])
                    continue;
                for (int k = 0; k <= 3; k++)
                {
                    if (g[i + dx[k]][j + dy[k]])
                    {
                        idx[i][j] = ++tot;
                        p[tot] = {i, j};
                    }
                    for (int x = i, y = j; !g[x][y]; x += dx[k], y += dy[k])
                        nxt[i][j][k] = {x, y};
                }
            }
        // 有效点对之间建反图
        for (int i = 1; i <= tot; i++)
            for (int j = 1; j <= tot; j++)
                for (int k = 0; k <= 3; k++)
                {
                    pair<int, int> pi = nxt[p[i].first][p[i].second][k];
                    pair<int, int> pj = nxt[p[j].first][p[j].second][k];
                    int ii = idx[pi.first][pi.second];
                    int jj = idx[pj.first][pj.second];
                    // i,j -> ii,jj
                    e[ii][jj].push_back({i, j});
                }
        // 重合点反向 bfs 预处理有效点对的 dis
        for (int i = 1; i <= tot; i++)
        {
            q.push({i, i});
            dis[i][i] = 1;
            vis[i][i] = true;
        }
        while (!q.empty())
        {
            int a = q.front().first;
            int b = q.front().second;
            q.pop();
            for (int i = 0; i < e[a][b].size(); i++)
            {
                int aa = e[a][b][i].first;
                int bb = e[a][b][i].second;
                if (vis[aa][bb])
                    continue;
                dis[aa][bb] = dis[a][b] + 1;
                vis[aa][bb] = true;
                q.push({aa, bb});
            }
        }
        // 回答每个问题,每个问题走一步之后就能到有效点对上
        while (Q--)
        {
            int a, b, c, d;
            cin >> a >> b >> c >> d;
            if (a == c && b == d)
            {
                cout << "0\n";
                continue;
            }
            int ans = -1;
            for (int i = 0; i <= 3; i++)
            {
                // 走了一个 i 方向可以到 (aa,bb),(cc,dd)
                int aa = nxt[a][b][i].first;
                int bb = nxt[a][b][i].second;
                int cc = nxt[c][d][i].first;
                int dd = nxt[c][d][i].second;
                int now = dis[idx[aa][bb]][idx[cc][dd]];
                if (!now)
                    continue;
                if (ans == -1 || now < ans)
                    ans = now;
            }
            cout << ans << "\n";
        }
    
        return 0;
    }
    
    • 1

    信息

    ID
    1790
    时间
    1000ms
    内存
    512MiB
    难度
    5
    标签
    递交数
    5
    已通过
    1
    上传者