Cod sursa(job #3326657)

Utilizator adriana_grGrama Adriana adriana_gr Data 29 noiembrie 2025 19:04:05
Problema Barbar Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.34 kb
#include <iostream>
#include <fstream>
#include <queue>
#include <string>

using namespace std;

ifstream fin("barbar.in");
ofstream fout("barbar.out");

int R, C;
int distD[1002][1002];     // distanta pana la cel mai apropiat dragon
int dl[] = {0, 0, 1, -1};
int dc[] = {-1, 1, 0, 0};

queue<pair<int,int>> q;

string linie;

bool valid(int x, int y)
{
    return (x >= 0 && x < R && y >= 0 && y < C);
}

void lee_dragoni()
{
    while (!q.empty())
    {
        int x = q.front().first;
        int y = q.front().second;
        q.pop();

        for (int d = 0; d < 4; d++)
        {
            int nx = x + dl[d];
            int ny = y + dc[d];

            if (valid(nx, ny))
            {
                if (distD[nx][ny] == -1)   // celula libera nevizitata
                {
                    distD[nx][ny] = distD[x][y] + 1;
                    q.push({nx, ny});
                }
            }
        }
    }
}

int start_x, start_y, exit_x, exit_y;

// verifica daca exista drum de la I la O cu distanta minima >= val
bool exista_drum(int val)
{
    if (distD[start_x][start_y] < val)
        return false;

    static int viz[1002][1002];
    for (int i = 0; i < R; i++)
        for (int j = 0; j < C; j++)
            viz[i][j] = 0;

    queue<pair<int,int>> coada;
    coada.push({start_x, start_y});
    viz[start_x][start_y] = 1;

    while (!coada.empty())
    {
        int x = coada.front().first;
        int y = coada.front().second;
        coada.pop();

        if (x == exit_x && y == exit_y)
            return true;

        for (int d = 0; d < 4; d++)
        {
            int nx = x + dl[d];
            int ny = y + dc[d];

            if (valid(nx, ny) && !viz[nx][ny])
            {
                if (distD[nx][ny] >= val)
                {
                    viz[nx][ny] = 1;
                    coada.push({nx, ny});
                }
            }
        }
    }

    return false;
}

int main()
{
    fin >> R >> C;

    // citim gridul ca stringuri
    vector<string> grid(R);
    for (int i = 0; i < R; i++)
        fin >> grid[i];

    // initializam distanta la -2 pentru pereti, -1 pentru celule libere
    for (int i = 0; i < R; i++)
    {
        for (int j = 0; j < C; j++)
        {
            if (grid[i][j] == '*')
                distD[i][j] = -2;    // perete
            else
                distD[i][j] = -1;    // vizitabil

            if (grid[i][j] == 'D')
            {
                distD[i][j] = 0;     // dragon = 0
                q.push({i, j});      // multi-sursa
            }

            if (grid[i][j] == 'I')
            {
                start_x = i;
                start_y = j;
            }

            if (grid[i][j] == 'O')
            {
                exit_x = i;
                exit_y = j;
            }
        }
    }

    // LEE de la dragoni → calculeaza distanta pana la cel mai apropiat dragon
    lee_dragoni();

    // cautare binara pe distanta minima ceruta
    int st = 0, dr = R + C, ans = -1;

    while (st <= dr)
    {
        int mid = (st + dr) / 2;

        if (exista_drum(mid))
        {
            ans = mid;
            st = mid + 1;
        }
        else
        {
            dr = mid - 1;
        }
    }

    fout << ans;
    return 0;
}