Cod sursa(job #2073840)

Utilizator BogdanisarBurcea Bogdan Madalin Bogdanisar Data 23 noiembrie 2017 19:22:56
Problema Barbar Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.06 kb
#include <iostream>
#include <fstream>
#include <queue>

#if 1
#define pv(x) cout<<#x<<" = "<<x<<"; ";cout.flush()
#define pn cout<<endl
#else
#define pv(x)
#define pn
#endif

using namespace std;
ifstream in("barbar.in");
ofstream out("barbar.out");

#define ll long long
#define ull unsigned long long
#define pb push_back
#define mp make_pair
const int NMax = 1e3 + 5;

int dx[4] = {-1,1,0,0}, dy[4] = {0,0,-1,1};

int N,M;
char a[NMax][NMax];
bool vis[NMax][NMax];
int distDragon[NMax][NMax];
// a[i][j] - valoarea caracter din input din celula (i,j);
// vis[i][j] = true, daca celula (i,j) a fost vizitata la parcurgerea curenta;
// distDragon[i][j] = distanta minima de la celula (i,j) la un dragon;

struct queueElement {
    int x,y,pasi;
    queueElement(int _x = 0,int _y = 0,int _pasi = 0): x(_x), y(_y), pasi(_pasi) {}
};

bool canEscape(int,int,int,int,int);

int main() {
    in>>N>>M;

    int xStart = 0,yStart = 0,xEnd = 0,yEnd = 0;
    queue< queueElement > Q;
    for (int i=1;i <= N;++i) {
        in>>(a[i]+1);

        for (int j=1;j <= M;++j) {
            if (a[i][j] == 'D') {
                // celulele in care se afla dragoni se introduc in coada ca pozitii de start;
                // pentru a construi distDragon;
                Q.push( queueElement(i,j,0) );
                distDragon[i][j] = 0;
                vis[i][j] = true;
            }
            else if (a[i][j] == 'I') {
                xStart = i;
                yStart = j;
            }
            else if (a[i][j] == 'O') {
                xEnd = i;
                yEnd = j;
            }
        }
    }

    // se relizeaza o parcurgere lee din fiecare celula care contine un dragon;
    // maxDist = maximul dintre distDragon[i][j];
    int maxDist = 0;
    while (Q.size()) {
        queueElement e = Q.front();
        Q.pop();

        for (int k=0;k < 4;++k) {
            int nx = e.x + dx[k],
                ny = e.y + dy[k];

            // daca se iese din matrice, dam de un perete sau daca am mai vizitat celula;
            if (nx < 1 || nx > N || ny < 1 || ny > M || a[nx][ny] == '*' || vis[nx][ny]) {
                continue;
            }

            distDragon[nx][ny] = e.pasi + 1;
            vis[nx][ny] = true;
            Q.push( queueElement(nx,ny,e.pasi + 1) );

            maxDist = max(maxDist,distDragon[nx][ny]);
        }
    }

    // se cauta binar solutia;
    int pw = 1, ans = 0;
    for (;pw <= maxDist;pw <<= 1) ;
    pw >>= 1;

    while (pw) {
        if ( canEscape(xStart,yStart,xEnd,yEnd, ans + pw) ) {
            ans += pw;
        }

        pw >>= 1;
    }

    // ca raspunsul sa nu existe, ans trebuie sa fie 0,
    // dar raspunsul poate exista cu ans fiind 0;
    if (ans == 0 && canEscape(xStart,yStart,xEnd,yEnd,0) == false) {
        out<<"-1\n";
    }
    else {
        out<<ans<<'\n';
    }

    return 0;
}

// functia determina daca Paftanie poate scapa mergand doar prin
// celule care au distanta minima mai mare sau egala cu minDist;
bool canEscape(int xStart,int yStart,int xEnd,int yEnd,int minDist) {
    if (distDragon[xStart][yStart] < minDist) {
        return false;
    }

    for (int i=1;i <= N;++i) {
        for (int j=1;j <= M;++j) {
            vis[i][j] = false;
        }
    }

    queue< pair<int,int> > Q;

    Q.push( mp(xStart,yStart) );
    while (Q.size()) {
        pair<int,int> p = Q.front();
        Q.pop();

        if (p.first == xEnd && p.second == yEnd) {
            return true;
        }

        for (int k=0;k < 4;++k) {
            int nx = p.first + dx[k],
                ny = p.second + dy[k];

            if (vis[nx][ny] || distDragon[nx][ny] < minDist) {
                continue;
            }

            // daca se iese din matrice sau daca dam de un perete;
            if (nx < 1 || nx > N || ny < 1 || ny > M || a[nx][ny] == '*') {
                continue;
            }

            vis[nx][ny] = true;
            Q.push( mp(nx,ny) );
        }
    }

    return false;
}