Cod sursa(job #1804881)

Utilizator vasi461Vasiliu Dragos vasi461 Data 13 noiembrie 2016 10:23:04
Problema Barbar Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.21 kb
#include <fstream>
#include <queue>
using namespace std;

#define INF 1000002
#define NM 1002

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

int n, m, x1, y1, x2, y2, d[NM][NM], dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}, dr[NM][NM];
queue<int> q;
bool viz[NM][NM];
char s[NM][NM];

bool coord(int cx, int cy)
{
    return (cx > 0 and cx <= n and cy > 0 and cy <= m);
}

void mat(int val)
{ 
    for(int i = 1; i <= n; ++i)
    {
        for(int j = 1; j <= m; ++j)
        {
            viz[i][j] = false;
            if(s[i][j] == '.' or s[i][j] == 'I' or s[i][j] == 'O')
            {
                d[i][j] = val;
            }
            if(s[i][j] == 'D')
            {
                d[i][j] = 0;
            }
            if(s[i][j] == '*')
            {
                d[i][j] = -1;
            }
            if(s[i][j] == 'I')
            {
                x1 = i;
                y1 = j;
            }
            if(s[i][j] == 'O')
            {
                x2 = i;
                y2 = j;
            }
        }
    }
}

void dragon()
{
    mat(INF);
    for(int i = 1; i <= n; ++i)
    {
        for(int j = 1; j <= m; ++j)
        {
            if(s[i][j] == 'D')
            {
                q.push(i);
                q.push(j);
                d[i][j] = 0;
            }
        }
    }
    while(!q.empty())
    {
        int x = q.front();
        q.pop();
        int y = q.front();
        q.pop();
        for(int i = 0; i < 4; ++i)
        {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if(coord(nx, ny))
            {
                if(d[nx][ny] == INF)
                {
                    d[nx][ny] = d[x][y] + 1;
                    q.push(nx);
                    q.push(ny);
                }
            }
        }
    }
    for(int i = 1; i <= n; ++i)
    {
        for(int j = 1; j <= m; ++j)
        {
            dr[i][j] = d[i][j];
        }
    }
}

bool exista_drum(int m)
{
    mat(-INF);
    if(dr[x1][y1] < m)
    {
        return false;
    }
    q.push(x1);
    q.push(y1);
    d[x1][y1] = dr[x1][y1];
    viz[x1][y1] = true;
    while(!q.empty())
    {
        int x = q.front();
        q.pop();
        int y = q.front();
        q.pop();
        for(int i = 0; i < 4; ++i)
        {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if(coord(nx, ny) and s[nx][ny] != '*' and dr[nx][ny] >= m)
            {
                if(!viz[nx][ny])
                {
                    q.push(nx);
                    q.push(ny);
                    viz[nx][ny] = true;
                }
            }
        }
    }
    return viz[x2][y2];
}

int main()
{
    cin >> n >> m;
    cin.getline(s[0], 1002);
    for(int i = 1; i <= n; ++i)
    {
        cin.getline(s[i] + 1, m + 2);
    }
    dragon();
    int st = 0, dre = INF, r = -1;   
    while(st <= dre)
    {
        int m = (st + dre) / 2;
        if(exista_drum(m))
        {
            r = m;
            st = m + 1;
        }
            else
            {
                dre = m - 1;
            }
    }
    cout << r << '\n';
    return 0;
}