Cod sursa(job #866937)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 28 ianuarie 2013 21:41:17
Problema Barbar Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.9 kb
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>

#define pp pair<int,int>
#define mp make_pair
#define ox first
#define oy second

using namespace std;

#define Nmax 1024

const int dl[]={ -1, 0, 1, 0};
const int dc[]={ 0, 1, 0, -1};

int mat[Nmax][Nmax];
bool viz[Nmax][Nmax];
char s[Nmax];

queue <pp> Q;
queue <pp> coada;

int R, C;
int xP, yP;
int xO, yO;
bool verif = false, solutie = false;
int minim;

void citire(){

    freopen("barbar.in", "rt", stdin);

    scanf("%d %d", &R, &C);

    for(int i = 1; i <= R; ++i){

        scanf("%s", s);

        for(int j = 0; j < C; ++j){

            if(s[j] == '*')
                mat[i][j+1] = -1;

            if(s[j] == 'I')
                xP = i, yP = j+1;

            if(s[j] == 'O')
                xO = i, yO = j+1;

            if(s[j] == 'D')
                mat[i][j+1] = 0,
                Q.push(mp(i,j+1)),
                coada.push(mp(i,j+1));
        }
    }
}

void bordare(){

    for(int i = 0; i <= C+1; i++)
        mat[0][i] = mat[R+1][i] = -1;

    for(int i = 0; i <= R+1; i++)
        mat[i][0] = mat[i][C+1] = -1;
}

void lee(){

    pp current, vecin;

    while(!Q.empty()){

        current = Q.front();

        Q.pop();

        for(int k = 0; k < 4; k++){

            vecin.ox = current.ox + dl[k];
            vecin.oy = current.oy + dc[k];

            if(mat[vecin.ox][vecin.oy] == 0)
                mat[vecin.ox][vecin.oy] = mat[current.ox][current.oy] + 1,
                Q.push(vecin);
        }
    }
}

void reinit(){

    while(!coada.empty()){

        mat[coada.front().ox][coada.front().oy] = 0;
        coada.pop();
    }
}

void drum(int dist){

    pp current, vecin;

    while(!Q.empty()){

        current = Q.front();
        viz[current.ox][current.oy] = true;
        Q.pop();

        if( current.ox == xO && current.oy == yO ){

            solutie = true;
            verif = true;

            while(!Q.empty())
                Q.pop();
        }

        for(int k = 0; k < 4; k++){

            vecin.ox = current.ox + dl[k];
            vecin.oy = current.oy + dc[k];

            if(mat[vecin.ox][vecin.oy] >= dist && !viz[vecin.ox][vecin.oy])
                Q.push(vecin),
                viz[vecin.ox][vecin.oy] = true;
        }
    }
}


void cautare_binara(){

    int stanga = -1;
    int dreapta = Nmax + Nmax;
    int dist;

    while ( dreapta - stanga > 1){

        dist = (dreapta + stanga) / 2;
        verif = false;

        memset(viz, false, sizeof(viz));
        Q.push(mp(xP, yP));
        drum(dist);

        if(verif)
            stanga = dist;
        else
            dreapta = dist;
    }

    minim  = min(stanga, mat[xP][yP]);

    if(!solutie)
        minim = -1;
}

void afis(){

    freopen("barbar.out", "w", stdout);

    printf("%d\n", minim);
}

int main(){

    citire();
    bordare();
    lee();
    reinit();
    cautare_binara();
    afis();

    return 0;
}