Cod sursa(job #690818)

Utilizator repp4raduRadu-Andrei Szasz repp4radu Data 25 februarie 2012 22:11:32
Problema Barbar Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.23 kb
#include <stdio.h>
#include <string.h>
#include <queue>

#define MAX 1050

using namespace std;

int matrice[MAX][MAX], dist[MAX][MAX], r, c, sol = -1;
int dX[4] = {-1, 0, 1, 0}, dY[4] = {0, 1, 0, -1};
bool visit[MAX][MAX];

struct point
{
    int x, y;
}start, stop;

queue<point> q;

void citire()
{
    freopen("barbar.in", "r", stdin);
    scanf("%d %d\n", &r, &c);
    int i, j;
    char aux;
    point add;
    for(i = 1; i <= r; i++)
    {
        for(j = 1; j <= c; j++)
        {
            scanf("%c", &aux);
            if(aux == 'D')
            {
                dist[i][j] = 1;
                visit[i][j] = true;
                add.x = i;
                add.y = j;
                q.push(add);
            }
            else if(aux == 'I')
            {
                start.x = i;
                start.y = j;
            }
            else if(aux == 'O')
            {
                stop.x = i;
                stop.y = j;
            }
            else if(aux == '*')
            {
                visit[i][j] = true;
                dist[i][j] = -1;
            }
        }
        scanf("\n");
    }
    fclose(stdin);
    for(i = 0; i <= c + 1; i++)
        dist[0][i] = dist[r + 1][i] = -1;
    for(i = 0; i <= r + 1; i++)
        dist[i][0] = dist[i][c + 1] = -1;
}

void genDist()
{
    int x, y, X, Y, i;
    point add;
    while(!q.empty())
    {
        x = q.front().x; y = q.front().y;
        q.pop();
        for(i = 0; i < 4; i++)
        {
            X = x + dX[i];
            Y = y + dY[i];
            if(!dist[X][Y])
            {
                dist[X][Y] = dist[x][y] + 1;
                visit[X][Y] = true;
                add.x = X; add.y = Y; q.push(add);
            }
            else
                if(dist[X][Y] > dist[x][y] + 1)
                    dist[X][Y] = dist[x][y] + 1;
        }
    }
}

void prepare()
{
    memset(visit, 0, MAX * MAX * sizeof(bool));
    while(!q.empty())
        q.pop();
    point add;
    add.x = start.x;
    add.y = start.y;
    q.push(add);
    visit[start.x][start.y] = true;
}

bool lee(int minimum)
{
    int x, y, X, Y, i;
    point add;
    while(!q.empty())
    {
        x = q.front().x; y = q.front().y;
        q.pop();
        for(i = 0; i < 4; i++)
        {
            X = x + dX[i];
            Y = y + dY[i];
            if(dist[X][Y] >= minimum && matrice[X][Y] >= 0 && !visit[X][Y])
            {
                visit[X][Y] = true;
                add.x = X; add.y = Y; q.push(add);
            }
            if(X == stop.x && Y == stop.y)
                return true;
        }
    }
    return false;
}

void cautare()
{
    int begin = 1, end = min(dist[start.x][start.y], dist[stop.x][stop.y]), mid = (begin + end) / 2;
    while(begin <= end)
    {
        prepare();
        if(lee(mid))
        {
            begin = mid + 1;
            sol = mid - 1;
        }
        else
            end = mid - 1;
        mid = (begin + end) / 2;
    }
}

void afisare()
{
    freopen("barbar.out", "w", stdout);
    printf("%d", sol);
    fclose(stdout);
}

int main()
{
    citire();
    genDist();
    cautare();
    afisare();
    return 0;
}