Cod sursa(job #938562)

Utilizator romircea2010FMI Trifan Mircea Mihai romircea2010 Data 12 aprilie 2013 21:10:20
Problema Barbar Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.87 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#define INF 2000000000

using namespace std;

struct punct
{
    int x, y;
};
punct start, finish;
int n, m, sol;
char a[1010][1010];
int d[1010][1010], d2[1010][1010];
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};
int dist[1010][1010];
queue <punct> Q;

inline void Read()
{
    ifstream f ("barbar.in");
    f>>n>>m;
    int i;
    for (i=1; i<=n; i++)
        f>>(a[i]+1);
    f.close();
}

inline void Bordare()
{
    int i, n1, m1;
    n1 = n+1, m1 = m+1;
    for (i=0; i<=n1; i++)
        a[i][0] = a[i][m1] = '*';
    for (i=0; i<=m1; i++)
        a[0][i] = a[n1][i] = '*';
}

inline void CalcDist ()
{
    Bordare();
    int i, j;
    for (i=1; i<=n; i++)
        for (j=1; j<=m; j++)
            d[i][j] = d2[i][j] = INF;
    punct aux;
    for (i=1; i<=n; i++)
        for (j=1; j<=m; j++)
            if (a[i][j] == 'D')
            {
                aux.x = i;
                aux.y = j;
                Q.push(aux);
                d[i][j] = 0;
            }
            else
                if (a[i][j] == 'I')
                    start.x = i, start.y = j;
                else
                    if (a[i][j] == 'O')
                        finish.x = i, finish.y = j;

    int k, x, y;

    while (!Q.empty())
    {
        aux = Q.front();
        Q.pop();
        x = aux.x;
        y = aux.y;
        for (k=0; k<4; k++)
        {
            if (a[x+dx[k]][y+dy[k]] != '*')
            {
                if (d[x][y] + 1 < d[x+dx[k]][y+dy[k]])
                {
                    d[x+dx[k]][y+dy[k]] = d[x][y] + 1;
                    aux.x = x+dx[k];
                    aux.y = y+dy[k];
                    Q.push(aux);
                }
            }
        }
    }
}

inline void CalcDist2 ()
{
    Q.push(start);
    d2[start.x][start.y] = 0;
    int k, x, y;
    punct aux;
    while (!Q.empty())
    {
        aux = Q.front();
        Q.pop();
        x = aux.x;
        y = aux.y;
        for (k=0; k<4; k++)
        {
            if (a[x+dx[k]][y+dy[k]] != '*')
            {
                if (d2[x][y] + 1 < d2[x+dx[k]][y+dy[k]])
                {
                    d2[x+dx[k]][y+dy[k]] = d2[x][y] + 1;
                    aux.x = x+dx[k];
                    aux.y = y+dy[k];
                    Q.push(aux);
                }
            }
        }
    }
}


inline bool Verif(int limit)
{
    int i, j;
    for (i=1; i<=n; i++)
        for (j=1; j<=m; j++)
            dist[i][j] = 0;
    dist[start.x][start.y] = 1;
    while (!Q.empty())
        Q.pop();
    Q.push(start);
    punct aux;
    int x, y, k;
    while(!Q.empty())
    {
        aux = Q.front();
        Q.pop();
        x = aux.x;
        y = aux.y;
        for (k=0; k<4; k++)
        {
            if (a[x+dx[k]][y+dy[k]] != '*' && dist[x+dx[k]][y+dy[k]] == 0 && d[x+dx[k]][y+dy[k]] >= limit)
            {
                if (x + dx[k] == finish.x && y + dy[k] == finish.y)
                    return true;
                dist[x+dx[k]][y+dy[k]] = 1;
                aux.x = x + dx[k];
                aux.y = y + dy[k];
                Q.push(aux);
            }
        }
    }
    return false;
}

inline void Solve()
{
    CalcDist();
    CalcDist2();
    if (d2[finish.x][finish.y] < d[finish.x][finish.y])
    {
        sol = d[start.x][start.y];
        return ;
    }
    int st, dr, mij;
    sol = -1;
    st = 0;
    dr = n+m-1;
    while (st<=dr)
    {
        mij = (st+dr)>>1;
        if (Verif(mij))
        {
            sol = mij;
            st = mij+1;
        }
        else
            dr = mij-1;
    }
}

inline void Write()
{
    ofstream g ("barbar.out");
    g<<sol<<"\n";
    g.close();
}


int main()
{
    Read();
    Solve();
    Write();
    return 0;
}