Cod sursa(job #1415508)

Utilizator depevladVlad Dumitru-Popescu depevlad Data 4 aprilie 2015 21:46:20
Problema Barbar Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.81 kb
#include <cstdio>
#include <cstring>
#include <queue>

using namespace std;

#define inFile "barbar.in"
#define outFile "barbar.out"
#define MAX_N 1000
#define INF 1<<30

FILE *in = fopen(inFile, "r");
FILE *out = fopen(outFile, "w");

struct POZ {
    short x;
    short y;
};

int n, m;
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};
char A[MAX_N + 5][MAX_N + 5];
bool U[MAX_N + 5][MAX_N + 5];
int D[MAX_N + 5][MAX_N + 5];
queue < POZ > q;

bool isPossible(int minDist, POZ START, POZ END);

int main() {
    short i, j, d, ni, nj;
    POZ START, END;

    fscanf(in, "%d %d\n", &n, &m);
    for(i = 0; i < n; i++)
        fgets(A[i], MAX_N, in);

    memset(D, -1, sizeof(D[0][0]) * MAX_N * MAX_N);

    for(i = 0; i < n; i++) {
        for(j = 0; j < m; j++) {
            if(A[i][j] == 'D') {
                A[i][j] = '.';
                D[i][j] = 0;
                q.push( {i,j} );
            }
            else if(A[i][j] == 'I') {
                START = {i,j};
                A[i][j] = '.';
            }
            else if(A[i][j] == 'O') {
                END = {i,j};
                A[i][j] = '.';
            }
        }
    }

    while(!q.empty()) {
        i = q.front().x;
        j = q.front().y;

        for(d = 0; d < 4; d++) {
            ni = i + dx[d];
            nj = j + dy[d];

            if(0 <= ni && ni < n && 0 <= nj && nj < m) {
                if(D[ni][nj] == -1 && A[ni][nj] == '.') {
                    D[ni][nj] = D[i][j] + 1;
                    q.push( {ni,nj} );
                }
            }
        }
        q.pop();
    }

    int sBeg = 0, sMid, sEnd = n*m, lastFound = -1;
    while(sBeg <= sEnd) {
        sMid = (sBeg + sEnd) >> 1;
        if(isPossible(sMid, START, END)) {
            lastFound = sMid;
            sBeg = sMid + 1;
        }
        else {
            sEnd = sMid - 1;
        }
    }

    fprintf(out, "%d\n", lastFound);

    return 0;
}

bool isPossible(int minDist, POZ START, POZ END) {
    memset(U, 0, sizeof(U[0][0]) * MAX_N * MAX_N);

    short i, j, ni, nj, d;
    bool Found = 0;

    i = START.x;
    j = START.y;
    if(D[i][j] < minDist) return 0;
    U[i][j] = 1;

    q.push(START);
    while(!q.empty() && !Found) {
        i = q.front().x;
        j = q.front().y;

        if(i == END.x && j == END.y)
            Found = 1;

        for(d = 0; d < 4; d++) {
            ni = i + dx[d];
            nj = j + dy[d];

            if(0 <= ni && ni < n && 0 <= nj && nj < m)
                if((D[ni][nj] >= minDist || D[ni][nj] == -1) && A[ni][nj] == '.' && !U[ni][nj]) {
                    U[ni][nj] = 1;
                    q.push( {ni,nj} );
                }
        }
        q.pop();
    }

    while(!q.empty()) q.pop();
    return Found;
}