Gym 100134L - Labyrinth of the Minotaur

版权声明: https://blog.csdn.net/moon_sky1999/article/details/87651121

题目来源:http://codeforces.com/gym/100134/attachments

题意:给一个迷宫,问是否存在一种方案,可以用一个正方形块,堵住从左上到右下的所有路径,输出坐标及正方形边长。

考虑到从起点到终点的方案可能会有很多,但可以确定所有路径集合的左右边界。而左右边界通常就是左手路径与右手路径。

关于左右手路径可以参考POJ 3083。

如果一个正方形既能够封锁左手路径,又能封锁右手路径,那么一定可以封锁所有路径。

可以枚举每一个点,作为正方形的左上角,再枚举正方形的边长。如果该正方形覆盖的区域既含有左手路径,又含有右手路径,同时没有障碍物,这样我们就可以认定该方案是合法的。

检验该方案的合法性可以采用前缀和的方法,即维护三个前缀和:障碍物的前缀和、左右手路径的前缀和。

枚举正方形的边长复杂度过高,可以采用二分查找的方法。二分能够同时覆盖左右手路径的边长的最小值,再检验该正方形区域内是否没有障碍物。这样复杂度即是O(n^2logn)。

注意正方形既不能覆盖起点,也不能覆盖终点。

代码:

#include <bits/stdc++.h>

using namespace std;

char a[1555][1555];
bool vis[1555][1555];
int n, m, suml[1555][1555], sumr[1555][1555], sumx[1555][1555];

int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};

void dfs(int x, int y, int p, int X) {
    vis[x][y] = 1;
    while (x != n || y != m) {
        if (X == 0) {
            for (int i = 0; i < 4; ++i) {
                int t = p + i + 3;
                t %= 4;
                if (x + dx[t] >= 1 && dx[t] <= n && y + dy[t] >= 1 && y + dy[t] <= m
                    && a[x + dx[t]][y + dy[t]] == '.') {
                    x += dx[t];
                    y += dy[t];
                    p = t;
                    break;
                }
            }
        } else {
            for (int i = p + 1; i > p - 3; --i) {
                int t = i + 4;
                t %= 4;
                if (x + dx[t] >= 1 && dx[t] <= n && y + dy[t] >= 1 && y + dy[t] <= m
                    && a[x + dx[t]][y + dy[t]] == '.') {
                    x += dx[t];
                    y += dy[t];
                    p = t;
                    break;
                }
            }
        }
        vis[x][y] = 1;
    }
}

int _get(int x, int y) {
    int l = 1, r = min(n - x, m - y) + 1;
    if (suml[x + r - 1][y + r - 1] - suml[x - 1][y + r - 1] - suml[x + r - 1][y - 1] + suml[x - 1][y - 1] == 0 ||
        sumr[x + r - 1][y + r - 1] - sumr[x - 1][y + r - 1] - sumr[x + r - 1][y - 1] + sumr[x - 1][y - 1] == 0)
        return 1e9;
    while (l < r) {
        int m = (l + r) >> 1;
        if (suml[x + m - 1][y + m - 1] - suml[x - 1][y + m - 1] - suml[x + m - 1][y - 1] + suml[x - 1][y - 1] > 0 &&
            sumr[x + m - 1][y + m - 1] - sumr[x - 1][y + m - 1] - sumr[x + m - 1][y - 1] + sumr[x - 1][y - 1] > 0)
            r = m;
        else l = m + 1;
    }
    if (sumx[x + l - 1][y + l - 1] - sumx[x - 1][y + l - 1] - sumx[x + l - 1][y - 1] + sumx[x - 1][y - 1] == 0) {
        if (x + l - 1 == n && y + l - 1 == m)return 1e9;
        else return l;
    }
    return 1e9;
}

int main() {
    freopen("labyrinth.in", "r", stdin);
    freopen("labyrinth.out", "w", stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> m >> n;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            cin >> a[i][j];
            sumx[i][j] = sumx[i - 1][j] + sumx[i][j - 1] - sumx[i - 1][j - 1];
            if (a[i][j] == '#')sumx[i][j]++;
        }
    }
    memset(vis, 0, sizeof vis);
    dfs(1, 1, 1, 0);
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            suml[i][j] = suml[i - 1][j] + suml[i][j - 1] - suml[i - 1][j - 1];
            if (vis[i][j])suml[i][j]++;
        }
    }
    memset(vis, 0, sizeof vis);
    dfs(1, 1, 2, 2);
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            sumr[i][j] = sumr[i - 1][j] + sumr[i][j - 1] - sumr[i - 1][j - 1];
            if (vis[i][j])sumr[i][j]++;
        }
    }
    int ans = 1e9, x, y;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            if ((i != 1 || j != 1) && (i != n || j != m) && a[i][j] == '.') {
                int t = _get(i, j);
                if (t < ans) {
                    ans = t;
                    x = i;
                    y = j;
                }
            }
        }
    }
    if (ans > 1e7)cout << "Impossible" << endl;
    else cout << ans << ' ' << y << ' ' << x << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/moon_sky1999/article/details/87651121
今日推荐