Cod sursa(job #1425766)

Utilizator AplayLazar Laurentiu Aplay Data 27 aprilie 2015 23:40:38
Problema Barbar Scor 40
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.51 kb
#include <stdio.h>
#include <string.h>
#include <vector>

#define NMAX 1001
#define DRAGON 'D'
#define EMPTY  '.'
#define START  'I'
#define END    'O'
#define VECINI 4

using namespace std;

int r, c, dist[NMAX][NMAX], dMax = 0, dMin = 1 << 30, coada[2][NMAX * NMAX + NMAX], viz[NMAX][NMAX], startI, startJ, endI, endJ, ans;
int veciniI[] = { -1, 0, 0, 1}, veciniJ[] = { 0, -1, 1, 0};
char matrix[NMAX][NMAX];
vector< pair<int, int> > dragoni;

int validIndexes(int i, int j) {
    if(i < 0 || i >= r) return 0;
    if(j < 0 || j >= c) return 0;
    return 1;
}

void distDragoni() {
    int currI, currJ, newI, newJ, first, last;
    first = 0;
    last = -1;
    for(int i = 0; i < dragoni.size(); ++i) {
        coada[0][++last] = dragoni[i].first;
        coada[1][last]   = dragoni[i].second;
        dist[dragoni[i].first][dragoni[i].second] = 1;
    }
    while(first <= last) {
        currI = coada[0][first];
        currJ = coada[1][first];
        for(int i = 0; i < VECINI; ++i) {
            newI = currI + veciniI[i];
            newJ = currJ + veciniJ[i];
            if(validIndexes(newI, newJ) && !dist[newI][newJ] && matrix[newI][newJ] == EMPTY
                          || matrix[newI][newJ] == START || matrix[newI][newJ] == END) {
                coada[0][++last] = newI;
                coada[1][last]   = newJ;
                dist[newI][newJ] = dist[currI][currJ] + 1;
                if(dist[newI][newJ] < dMin) dMin = dist[newI][newJ];
                if(dist[newI][newJ] > dMax) dMax = dist[newI][newJ];
            }
        }
        ++first;
    }
}

int bfs(int limit) {
    int currI, currJ, newI, newJ, first, last;
    if(dist[startI][startJ] < limit || dist[endI][endJ] < limit) return 0;
    for(int i = 0; i < r; ++i)
        for(int j = 0; j < c; ++j)
            viz[i][j] = 0;
    first = last = 0;
    coada[0][0] = startI;
    coada[1][0] = startJ;
    viz[startI][startJ] = 1;
    while(first <= last) {
        currI = coada[0][first];
        currJ = coada[1][first];
        for(int i = 0; i < VECINI; ++i) {
            newI = currI + veciniI[i];
            newJ = currJ + veciniJ[i];
            if(validIndexes(newI, newJ) && !viz[newI][newJ] && dist[newI][newJ] >= limit) {
                coada[0][++last] = newI;
                coada[1][last]   = newJ;
                viz[newI][newJ]  = 1;
                if(newI == endI && newJ == endJ) return 1;
            }
        }
        ++first;
    }
    return 0;
}

void solve() {
    int m, canBeDone;
    ans = -1;
    distDragoni();
    while(dMin <= dMax) {
        m = (dMin + dMax) / 2;
        canBeDone = bfs(m);
        if(canBeDone && canBeDone > ans) ans = m;
        if(canBeDone) {
            dMin = m + 1;
        }
        else {
            dMax = m - 1;
        }
    }
}

int main() {
    freopen("barbar.in", "r", stdin);
    freopen("barbar.out", "w", stdout);

    scanf("%d%d%*c", &r, &c);
    for(int i = 0; i < r; ++i) {
        scanf("%s", matrix[i]);
        int index = 0;
        while(matrix[i][index]) {
            if(matrix[i][index] == DRAGON)
                dragoni.push_back(make_pair(i, index));
            if(matrix[i][index] == START) {
                startI = i;
                startJ = index;
            }
            if(matrix[i][index] == END) {
                endI = i;
                endJ = index;
            }
            ++index;
        }
    }

    solve();

    printf("%d", ans - 1);

    return 0;
}