Cod sursa(job #429202)

Utilizator vlad_DVlad Dumitriu vlad_D Data 29 martie 2010 22:12:13
Problema Barbar Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.31 kb
#include <cstdio>
#include <iostream>
#include <vector>

using namespace std;
char v[1001][1001];
int n, m;
int P[1000*1001], rank[1000*1001];
int D[1001][1001];
int Q[1001*2001];
int di[] = {0, 0, -1, 1}, dj[] = {1, -1, 0, 0};
int findSet(int x) {
    if (P[x] != x) return P[x] = findSet(P[x]);
    return P[x];
}
void mergeSet(int x, int y) {
    x = findSet(x);
    y = findSet(y);
    if (rank[x] > rank[y]) P[y] = x;
    else P[x] = y;
    if (rank[x] == rank[y]) rank[y] = rank[y] + 1;
}
vector<int> S[1000*1001];
void baga(int x, int y, int dist) {
    for (int d = 0; d < 4; ++d) {
        int nx = x + di[d], ny = y + dj[d];
        if (nx < 0 || ny < 0 || nx >= n || ny >= m) continue;
        if (v[nx][ny] != '.') continue;
        if (D[nx][ny] < dist) continue;
        mergeSet(x * 1000 + y, nx * 1000 + ny);
    }
}
int main() {
    freopen("barbar.in", "r", stdin);
    freopen("barbar.out", "w", stdout);

    scanf("%d %d", &n, &m);

    int ix, iy, ox, oy;

    for (int i = 0; i < n; ++i) {
        char line[1001];
        scanf("%s", &line);
        for (int j = 0; j < m; ++j) {
            v[i][j] = line[j];
            P[i*1000 + j] = i*1000 + j;
            D[i][j] = n * m * 500;
            if (v[i][j] == 'I') v[i][j] = '.', ix = i, iy = j;
            if (v[i][j] == 'O') v[i][j] = '.', ox = i, oy = j;
            if (v[i][j] == 'D') v[i][j] = '.', D[i][j] = 0, Q[++Q[0]] = i *
                1000 + j;
        }
    }

    for (int i = 1; i <= Q[0]; ++i) {
        int nx = Q[i] / 1000, ny = Q[i] % 1000;
        for (int d = 0; d < 4; ++d) {
            int xx = nx + di[d], yy = ny + dj[d];
            if (xx < 0 || yy < 0 || xx >= n || yy >= m) continue;
            if (v[xx][yy] != '.') continue;
            if (D[xx][yy] <= D[nx][ny] + 1) continue;
            D[xx][yy] = D[nx][ny] + 1;
            Q[++Q[0]] = xx * 1000 + yy;
        }
    }

    for (int i = 0; i < n; ++i)
        for (int j = 0; j < m; ++j) if (v[i][j] == '.' && D[i][j] <= n * m)
            S[D[i][j]].push_back(i * 1000 + j);
    for (int i = n * m; i >= 0; i--) {
        for (int j = 0; j < S[i].size(); ++j) {
            baga(S[i][j] / 1000, S[i][j] % 1000, i);
        }
        if (findSet(ix * 1000 + iy) == findSet(ox * 1000 + oy)) {
            printf("%d\n", i);
            return 0;
        }
    }
    printf("-1\n");
    return 0;
}