Cod sursa(job #3310601)

Utilizator MihaiZ777MihaiZ MihaiZ777 Data 15 septembrie 2025 14:42:35
Problema Barbar Scor 40
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.58 kb
#include <algorithm>
#include <array>
#include <cassert>
#include <cmath>
#include <deque>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
#include <cstring>
#include <fstream>
using namespace std;
using ll  = long long;

#define fast_io ios::sync_with_stdio(false); fin.tie(nullptr);
#define all(x)  (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define vec_read(v, n)                \
    for (int i = 0; i < (n); i++) {   \
        fin >> v[i];                  \
    }
#define vec_print(v, n, sp)           \
    for (int i = 0; i < (n); i++) {   \
        fout << v[i] << sp;           \
    }                                 \
    fout << '\n';
#define vec_print_rev(v, n, sp)          \
    for (int i = (n) - 1; i>= 0; i--) {  \
        fout << v[i] << sp;              \
    }                                    \
    fout << '\n';
#ifdef LOCAL
    #define dbg(x) cerr << #x << " = " << (x) << '\n'
#else
    #define dbg(x)
#endif

const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const int MAXN = 1e3 + 5;

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

pair<int,int> dirs[] = {{1, 0}, {-1, 0}, {0, -1}, {0, 1}};

int n, m;
char mat[MAXN][MAXN];
int distances[MAXN][MAXN];
vector<pair<int, int>> dragons;
pair<int, int> start, finish;
bool visited[MAXN][MAXN];

void ReadData() {
    fin >> n >> m;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            fin >> mat[i][j];
            if (mat[i][j] == 'D') {
                dragons.push_back({i, j});
            } else if (mat[i][j] == 'I') {
                start = {i, j};
            } else if (mat[i][j] == 'O') {
                finish = {i, j};
            }
        }
    }
}

bool InBounds(pair<int, int>& dir) {
    return !(dir.first < 0 || dir.second < 0 || dir.first >= n || dir.second >= m);
}

void BuildDistances() {
    for (int i = 0; i < n; i++) {
        memset(distances[i], INF, sizeof(distances[i]));
    }
    queue<pair<int,int>> q;
    for (auto d : dragons) {
        distances[d.first][d.second] = 0;
        q.push(d);
    }
    while (!q.empty()) {
        auto d = q.front();
        q.pop();

        for (int i = 0; i < 4; i++) {
            pair<int,int> dir = {d.first + dirs[i].first, d.second + dirs[i].second};
            if (!InBounds(dir)) {
                continue;
            }
            if (mat[dir.first][dir.second] == '*') {
                continue;
            }
            if (distances[dir.first][dir.second] != INF) {
                continue;
            }
            distances[dir.first][dir.second] = distances[d.first][d.second] + 1;
            q.push(dir);
        }
    }
}

struct Cell {
    pair<int, int> pos;
    int val;
    bool operator <(const Cell& other) const {
        return val < other.val;
    }
};

int BuildPath(int dist) {
    queue<Cell> q;
    q.push({start, distances[start.first][start.second]});
    int ans = INF;
    for (int i = 0; i < n; i++) {
        memset(visited[i], 0, sizeof(visited[i]));
    }

    while (!q.empty()) {
        auto d = q.front();
        q.pop();
        ans = min(ans, distances[d.pos.first][d.pos.second]);
        if (d.pos == finish) {
            return ans;
        }
        visited[d.pos.first][d.pos.second] = true;

        for (int i = 0; i < 4; i++) {
            pair<int,int> dir = {d.pos.first + dirs[i].first, d.pos.second + dirs[i].second};
            if (!InBounds(dir)) {
                continue;
            }
            if (mat[dir.first][dir.second] == '*') {
                continue;
            }
            if (visited[dir.first][dir.second]) {
                continue;
            }
            if (distances[dir.first][dir.second] < dist) {
                continue;
            }
            q.push({dir, distances[dir.first][dir.second]});
        }
    }
    return -1;
}

void Solve() {
    BuildDistances();
    int lf = 0;
    int rg = n + m + 1;
    int mid;
    int ans = -1;
    while (lf <= rg) {
        mid = lf + (rg - lf) / 2;
        if (BuildPath(mid) != -1) {
            lf = mid + 1;
            ans = max(ans, mid);
        } else {
            rg = mid - 1;
        }
    }
    fout << ans << '\n';
}

int main() {
    // fast_io;
    #ifdef LOCAL
        freopen("in.txt", "r", stdin);
        freopen("out.txt", "w", stdout);
    #endif
    int T = 1;
    // fin >> T;
    while (T--) {
        ReadData();
        Solve();
    }
    return 0;
}