Cod sursa(job #867916)

Utilizator mvcl3Marian Iacob mvcl3 Data 30 ianuarie 2013 12:58:02
Problema Barbar Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.78 kb
#include<fstream>
#include<queue>
#include<cstring>
using namespace std;

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

const int NMAX = 1005;
int n, m, ls, cs, lf, cf, d, x[NMAX][NMAX], viz[NMAX][NMAX];
short dl[4] = {-1, 0, 0, 1};
short dc[4] = {0, -1, 1, 0};
struct nod
{
    int l;
    int c;
    nod(){};
    nod(int a, int b)
    {
        l = a;
        c = b;
    };
};

queue<nod> q;

inline void citire();
inline void LEE();
inline bool cauta(int);
inline void solve();

int main()
{
    citire();
    LEE();

    if(x[ls][cs] == -2) // barbarul se afla intre * => nu are cum sa iasa => problema nu are sol
    {
        g<<-1<<'\n';
        g.close();
        return 0;
    }

    solve();

    g<<d<<'\n';

    g.close();
    return 0;
}

inline void citire()
{
    f>>n>>m;
    char ch;
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j)
            x[i][j] = -2;
    for(int i = 0; i <= n + 1; ++i) x[i][0] = x[i][m + 1] = -1;
    for(int j = 0; j <= m + 1; ++j) x[0][j] = x[n + 1][j] = -1;

    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j)
        {
            f>>ch;
            switch(ch)
            {
                case 'I' : {ls = i; cs = j; break;}
                case 'O' : {lf = i; cf = j; break;}
                case 'D' : {q.push(nod(i, j)); x[i][j] = 0; break;}
                case '*' : {x[i][j] = -1; break;}
            }
        }
}

inline void LEE()
{
    while(!q.empty())
    {
        int l =q.front().l, c = q.front().c;
        q.pop();
        for(int k = 0; k < 4; ++k)
        {
            int ll = dl[k] + l, cc = c + dc[k];
            if(x[ll][cc] == -2)
            {
                x[ll][cc] = x[l][c] + 1;
                q.push(nod(ll, cc));
            }
        }
    }
}

inline void solve()
{
    int st = 1, dr = n * m, m;
    while(st <= dr)
    {
        m = (st + dr) / 2;
        int ok = cauta(m);
        if(ok) // am gasit o valoare maxima si incerc sa gasesc alta mai mare st = m + 1
        {
            d = m;
            st = m + 1;
        }
        else
            dr = m - 1;
    }
}

inline bool cauta(int k)
{
    if(x[ls][cs] < k) return 0;
    q.push(nod(ls, cs));
    memset(viz, 0, sizeof(viz));
    viz[ls][cs] = 1; //vizitat
    while(!q.empty())
    {
        int l = q.front().l, c = q.front().c;
        q.pop();
        for(int i = 0; i < 4; ++i)
        {
            int ll = l + dl[i], cc = c + dc[i];
            if(!viz[ll][cc] && x[ll][cc] >= k) // caut maximul dintre minime considerandu-l pe k ca fiind minim-ul
            {
                q.push(nod(ll, cc));
                viz[ll][cc] = 1;
            }
        }
    }
    if(viz[lf][cf]) return 1;
    return 0;
}