Cod sursa(job #1368736)

Utilizator DorelBarbuBarbu Dorel DorelBarbu Data 2 martie 2015 19:42:59
Problema Barbar Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.09 kb
#include <iostream>
#include <cstdio>
#include <vector>
#include <deque>
using namespace std;

const int MAXRC = 1000, INF = 2000000000;

char map[MAXRC+1][MAXRC+1];

int R, C, dd[MAXRC+1][MAXRC+1], distMax;

struct poz
{
    int x;
    int y;
};

vector <poz> dragon;
poz start, finish;

bool inMatrix(int x, int y)
{
    return 1 <= x && x <= R && 1 <= y && y <= C;;
}

void citire()
{
    scanf("%d %d\n",&R,&C);
    char x;
    //scanf("%c",'\n');

    for(int i = 1; i <= R; i++)
    {
        for(int j = 1; j <= C; j++)
        {
            scanf("%c",&map[ i ][ j ]);

            if( map[ i ][ j ] == 'D' )
            {
                poz noua; noua.x = i; noua.y = j;
                dragon.push_back( noua );
            }
            else if( map[ i ][ j ] == 'I' )
                start.x = i, start.y = j;
            else if( map[ i ][ j ] == 'O' )
                finish.x = i, finish.y = j;

            dd[ i ][ j ] = INF;

        }

        scanf("\n");
    }
}

void testCitire()
{
    for(int i = 1; i <= R; i++)
    {
        for(int j = 1; j <= C; j++)
            cout<<map[ i ][ j ]<<' ';
        cout<<endl;
    }
}

void testDragon()
{
    for(int i = 0; i < dragon.size(); i++)
        cout<<dragon[ i ].x<<' '<<dragon[ i ].y<<endl;
}

void findDistMinDragon(poz drag)
{
    deque <poz> c; dd[ drag.x ][ drag.y ] = 0;  c.push_back( drag );
    int dx[] = { -1, 0, 1, 0 }; int dy[] = { 0, 1, 0, -1 };

    while( c.empty() == false )
    {
        poz nc = c[ 0 ]; c.pop_front();

        for(int i = 0; i < 4; i++)
        {
            poz next; next.x = nc.x + dx[ i ]; next.y = nc.y + dy[ i ];
            if( inMatrix( next.x, next.y ) == true && map[ next.x ][ next.y ] != '*' )
            {
                int dist = dd[ nc.x ][ nc.y ] + 1;

                if( dist < dd[ next.x ][ next.y ] )
                {
                    dd[ next.x ][ next.y ] = dist;
                    c.push_back( next );

                    distMax = max( distMax, dist );
                }
            }
        }
    }
}

void testFindDistMinDragon()
{
    for(int i = 1; i <= R; i++)
    {
        for(int j = 1; j <= C; j++)
            cout<<dd[ i ][ j ]<<' ';
        cout<<endl;
    }
}


void handleDragons()
{
    for(int i = 0; i < dragon.size(); i++)
        findDistMinDragon( dragon[ i ] );
}

bool viz[MAXRC+1][MAXRC+1];

void zeroViz()
{
    for(int i = 1; i <= R; i++)
        for(int j = 1; j <= C; j++)
            viz[ i ][ j ] = false;
}

bool tryDist(int distance)
{
    deque <poz> c; c.push_back( start );
    int dx[] = { -1, 0, 1, 0 }; int dy[] = { 0, 1, 0, -1 };

    zeroViz();

    while( c.empty() == false )
    {
        poz nc = c[ 0 ]; c.pop_front();

        for(int i = 0; i < 4; i++)
        {
            poz next; next.x = nc.x + dx[ i ]; next.y = nc.y + dy[ i ];
            if( inMatrix( next.x, next.y ) == true && viz[ next.x ][ next.y ] == false && map[ next.x ][ next.y ] != '*' )
            {
                if( distance <= dd[ next.x ][ next.y ] )
                {
                    c.push_back( next );
                    viz[ next.x ][ next.y ] = true;

                    if( next.x == finish.x && next.y == finish.y )
                        return true;
                }
            }
        }
    }

    return false;
}


int sol = 0;
bool sePoate = false;

void cautBin(int left, int right)
{
    while( left <= right )
    {
        int m = (left + right)/2;

        if( tryDist( m ) == true )
            sol = m, left = m + 1, sePoate = true;
        else right = m - 1;
    }
}

void afis()
{
    if( sePoate == true )
        cout<<sol;
    else cout<<-1;
}

int main()
{
    freopen("barbar.in","r",stdin);
    freopen("barbar.out","w",stdout);
    citire();
    //testCitire();
    //testDragon();
    //findDistMinDragon(dragon[0]);
    handleDragons();
    //cout<<distMax<<endl;
    //cout<<tryDist( 8 );

    cautBin(0, distMax);

    //testFindDistMinDragon();
    afis();
    return 0;
}