Cod sursa(job #1599236)

Utilizator BugirosRobert Bugiros Data 13 februarie 2016 18:40:34
Problema Barbar Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.46 kb
#include <fstream>
using namespace std;

ifstream in("barbar.in");
ofstream out("barbar.out");

const int MAXN = 1005;

inline int abs(int x)
{
    return (x < 0)?-x:x;
}


struct coordonata
{
    int x,y;

    coordonata operator + (coordonata &c)
    {
        coordonata rasp;
        rasp.x = this -> x + c.x;
        rasp.y = this -> y + c.y;
        return rasp;
    }

    bool operator == (coordonata &c)
    {
        return this -> x == c.x && this -> y == c.y;
    }
};

bool zid[MAXN][MAXN];

int dist[MAXN][MAXN];

int n,m;

coordonata start,finish;
coordonata dragon[MAXN * MAXN];
int nrdragoni = 0;

int vizitat[MAXN][MAXN];//retine momentul de timp cand a fost vizitat
int timp = 1;

void citire()
{
    char sir[MAXN];
    in >> n >> m;
    for (int i = 1;i <= n;++i)
    {
        zid[i][0] = true;
        zid[i][m + 1] = true;
        vizitat[i][0] = true;
        vizitat[i][m + 1] = true;
        in >> (sir + 1);
        for (int j = 1;j <= m;++j)
        {
            zid[0][j] = true;
            zid[n + 1][j] = true;
            vizitat[0][j] = true;
            vizitat[n + 1][j] = true;
            if (sir[j] == 'I')
            {
                start.x = i;
                start.y = j;
            }
            if (sir[j] == 'O')
            {
                finish.x = i;
                finish.y = j;
            }
            if (sir[j] == 'D')
            {
                ++nrdragoni;
                dragon[nrdragoni].x = i;
                dragon[nrdragoni].y = j;
            }
            if (sir[j] == '*')
                zid[i][j] = true;
        }
    }
}


coordonata coada[MAXN * MAXN];
int p,q;

coordonata off[4] = { (coordonata){-1,0} , (coordonata){1,0} , (coordonata){0,1} , (coordonata){0,-1}  };




bool dfs(int r)
{
    if (zid[start.x][start.y])
        return false;
    p = 1, q = 1;
    coada[1] = start;
    ++timp;
    vizitat[start.x][start.y] = timp;
    while (p <= q)
    {
        coordonata c = coada[p];
        ++p;
        for (int dir = 0; dir < 4;++dir)
        {
            coordonata vecin = c + off[dir];
            if (zid[vecin.x][vecin.y] || vizitat[vecin.x][vecin.y] == timp || dist[vecin.x][vecin.y] < r)
                continue;
            coada[++q] = vecin;
            vizitat[vecin.x][vecin.y] = timp;
            if (vecin == finish)
                return true;
        }
    }
    return false;
}

int cautare_binara()
{
    int poz = 0;
    for (int pas = 1 << 11;pas >= 1;pas >>= 1)
    {
        int r = poz + pas;
        if (r <= n && r <= m && dfs(r))
            poz += pas;
    }
    return poz;
}

void calculare_dragoni()
{
    p = 1,q = 0;
    for (int i = 1;i <= nrdragoni;++i)
    {
        coada[++q] = dragon[i];
        vizitat[dragon[i].x][dragon[i].y] = true;
    }
    while (p <= q)
    {
        coordonata c = coada[p];
        ++p;
        for (int dir = 0; dir < 4;++dir)
        {
            coordonata vecin = c + off[dir];
            if (vizitat[vecin.x][vecin.y] || zid[vecin.x][vecin.y])
                continue;
            coada[++q] = vecin;
            vizitat[vecin.x][vecin.y] = true;
            dist[vecin.x][vecin.y] = dist[c.x][c.y] + 1;
        }
    }
}

int main()
{
    citire();
    calculare_dragoni();
    int raspuns = cautare_binara();
    if (raspuns == 0)
        out << -1 << '\n';
    else out << raspuns << '\n';
    return 0;
}