Cod sursa(job #3316480)

Utilizator TeodoRazvanStancu Teodor-Razvan TeodoRazvan Data 18 octombrie 2025 21:48:31
Problema Barbar Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.51 kb
#include <bits/stdc++.h>
#include <fstream>
using namespace std;

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

const int di[] = {0,0,-1,1}, dj[] = {-1,1,0,0};
const int MAXN = 1005;
const int INF = 1e9;

int n, m;
int a[MAXN][MAXN];   // dragon reach time (0..), wall = -1, unreachable = INF
int h[MAXN][MAXN];   // visited timestamp for barbarian BFS
int si, sj, fi, fj;

bool ok(int i,int j){
    return i>=1 && j>=1 && i<=n && j<=m;
}

// check if barbarian, starting after 'wait' minutes (mij), can reach O
bool can_escape(int att, int wait){
    // clear the queue used by the barbarian BFS
    static queue<pair<short,short>> q;
    while(!q.empty()) q.pop();

    // if start cell is already reached by dragon before or at 'wait', cannot start
    if(a[si][sj] != -1 && a[si][sj] < wait) return false;
    if(a[si][sj] == -1) {
        // If si,sj is wall (shouldn't be normally), cannot start.
        return false;
    }

    // push start and mark visited with current timestamp
    q.push({(short)si,(short)sj});
    h[si][sj] = att;

    while(!q.empty()){
        auto p = q.front(); q.pop();
        int i = p.first, j = p.second;
        if(i==fi && j==fj) return true; // reached exit

        for(int k=0;k<4;k++){
            int ni = i + di[k], nj = j + dj[k];
            if(!ok(ni,nj)) continue;
            if(h[ni][nj] == att) continue;       // already visited this run
            if(a[ni][nj] == -1) continue;        // wall
            if(a[ni][nj] < wait) continue;       // dragon arrives before/at 'wait' -> unsafe
            // safe to push
            h[ni][nj] = att;
            q.push({(short)ni,(short)nj});
        }
    }
    return false;
}

int main(){
    fin >> n >> m;
    char c;

    // initialize
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            a[i][j] = INF;
            h[i][j] = 0;
        }
    }

    // Read grid and collect dragon sources
    queue<pair<int,int>> dq; // dragon BFS queue (separate)
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            fin >> c;
            if(c == '*'){
                a[i][j] = -1;   // wall
            } else if(c == 'I'){
                si = i; sj = j;
            } else if(c == 'O'){
                fi = i; fj = j;
            } else if(c == 'D'){
                a[i][j] = 0;    // dragon source reaches here at time 0
                dq.push({i,j});
            } // empty cells remain INF
        }
    }

    // Dragon BFS: compute earliest time dragon reaches each cell
    int maxTime = 0;
    while(!dq.empty()){
        auto p = dq.front(); dq.pop();
        int i = p.first, j = p.second;
        int curT = a[i][j]; // non-negative (0..)
        for(int k=0;k<4;k++){
            int ni = i + di[k], nj = j + dj[k];
            if(!ok(ni,nj)) continue;
            if(a[ni][nj] != INF) continue; // wall (-1) or already assigned a time
            a[ni][nj] = curT + 1;
            maxTime = max(maxTime, a[ni][nj]);
            dq.push({ni,nj});
        }
    }

    // Binary search over wait time
    int st = 0, dr = maxTime; // 0..maxTime inclusive
    int rez = -1;
    int att = 1; // timestamp marker for h
    while(st <= dr){
        int mid = (st + dr) / 2;
        bool okEscape = can_escape(att, mid);
        att++;
        if(okEscape){
            rez = max(rez, mid);
            st = mid + 1;
        } else {
            dr = mid - 1;
        }
    }

    fout << rez << "\n";
    return 0;
}