Cod sursa(job #995983)

Utilizator blasterzMircea Dima blasterz Data 10 septembrie 2013 17:25:59
Problema Barbar Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.35 kb
#include <cstdio>
#include <queue>
#include <cstring>
 
using namespace std;
 
#define N 1001
int R, C, d[N][N];
bool used[N][N]; // avem nevoie sa stim daca am procesat casuta (i, j)
char v[N][N];
 
int xx[4] = {-1, 0, 1, 0};
int yy[4] = {0, 1, 0, -1}; // le vom folosi la bfs/lee ca sa nu avem 4 ifuri ci facem un for in schimb
 
// o alta chestie: struct
// sau hai sa o denumim cell
// deci un cell mentine x si y, adica linia si coloana
struct cell {
    int x, y;
    cell() {};// e o fctie care initializeaza celula cand o declari goala
    cell(int _x, int _y) { // o fctie care o initializeaza cand ii dai parametri
    // de ex cell x(3,4); va crea o celula cu x = 3 si y = 4
        x = _x;
        y = _y;
    }
};

cell Q[1000010];
int first, last;

// mai avem nevoie de o coada
 
void read() {
    freopen ("barbar.in", "r", stdin);
    scanf ("%d %d\n", &R, &C);
    int i, j;
    for (i = 1; i <= R; ++i)
        scanf ("%s\n", v[i] + 1);
}
 
inline bool isOk(int i, int j) { // verifica daca (i, j) e in matrice
    if (i >= 1 && i <= R && j >= 1 && j <= C)
        return true;
    return false;
}
 
// BreadthFirstSearch
void bfs() {
    // punem in coada toti dragonii
    //queue<cell> Q; // asta e o coada, stii ce e coada?NU
    // e o structura care imita coada de la paine
    // cand vine un nou element, se aseaza la final, cand cel care a cumparat painea pleaca
 
    //trebuie sa punem toti dragonii in coada
    int i, j;
    first = 1; last = 0;

    for (i = 1; i <= R; ++i)
        for (j = 1; j <= C; ++j)
            if (v[i][j] == 'D')
                d[i][j] = 0,//distanta pana la un dragon e 0 pt ca ai deja dragon in (i, j)
                used[i][j] = true,
                Q[++last] = cell(i, j);//Q.push( cell(i, j) ); //push adauga la finalul cozii
 
    // acum facem bfs-ul propriu-zis
 
    while (first <= last) { //cat timp mai avem elemente in coada
        cell u = Q[first++]; // luam prima celula (cea care trebuie sa 'cumpere' paine')
        used[u.x][u.y] = true;// am procesat casuta
        // si acum ne uitam la casutele adiacente pe care nu le-am procesat deja
        for (int ii = 0; ii < 4; ++ii) { // merg pe cele 4 casute
            cell new_u( u.x + xx[ii], u.y + yy[ii] );
            //verific ca celula sa nu iasa din matrice
            if (isOk(new_u.x, new_u.y))
                if (v[new_u.x][new_u.y] != '*' && !used[new_u.x][new_u.y]) { // daca nu e procesata
                    d[new_u.x][new_u.y] = d[u.x][u.y] + 1;
                    Q[++last] = new_u;
                    //Q.push( new_u ); // adaugam in coada
                }
        }
    }
 
 
}
 
bool findPath(int minDistance) {
    memset (used, 0, sizeof(used)); // setez used la 0
    // iar facem BFS, dar acum il facem de la I la O 
    //queue<cell> Q;
    // punem in Q celula lui I
    first = 1; last = 0;
    int i, j;
    cell dest;
    for (i = 1; i <= R; ++i)
        for (j = 1; j <= C; ++j)
            if (v[i][j] == 'I')
                used[i][j] = true,
                Q[++last] = cell(i, j); //.push( cell(i, j) );
            else if (v[i][j] == 'O')
                dest = cell(i, j);
    
    cell u, new_u;
    while (first <= last) {
        u = Q[first++];
        used[u.x][u.y] = true;
        if (u.x == dest.x && u.y == dest.y) // am ajuns la destinatie, deci exista drum
            return true;
        for (int ii = 0; ii < 4; ++ii) {
            new_u = cell(u.x + xx[ii], u.y + yy[ii]);
            if (isOk(new_u.x, new_u.y) && v[new_u.x][new_u.y] != '*' && !used[new_u.x][new_u.y]) {
                if (d[new_u.x][new_u.y] >= minDistance)
                    Q[++last] = new_u;//Q.push(new_u);
            }
        }
    }
    return false;
}
 
void solve() {
    // prima etapa e sa calculam d[i][j] = distanta minima pana la cel mai apropiat dragon
    bfs();
 
    // acum trecem la partea a2a unde trebuie sa cautam binar rezultatul
    int i, cnt;
    bool found = false;
    for (i = 0, cnt = (1 << 10); cnt; cnt >>= 1)
        if (findPath(i + cnt))
            i += cnt,
            found = true;
     
    freopen ("barbar.out", "w", stdout);
    if (!found)
        printf ("-1\n");
    else
        printf ("%d\n", i);
    // deci eu caut binar cel mai mare i pentru care exista drum
    // functia findPath imi va spune daca exista drum
}
 
int main() {
    read();
    // cand ai o problema care va avea o sursa mare e bine sa verifici pasii majori
    solve();
}