Cod sursa(job #2928732)

Utilizator Alex18maiAlex Enache Alex18mai Data 23 octombrie 2022 19:06:57
Problema Barbar Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.29 kb
//ALEX ENACHE

#include <fstream>
#include <vector>
#include <queue>

using namespace std;

//ifstream cin("input"); ofstream cout("output");
ifstream cin("barbar.in"); ofstream cout("barbar.out");

const int inf = 1e9;
const int MAXN = 1010;

queue < pair < int , int> > q;
int obst[MAXN][MAXN];
int dist[MAXN][MAXN];
int used[MAXN][MAXN];

int dirx[] = { 0 , 0 , 1 , -1 };
int diry[] = { 1 , -1 , 0 , 0 };

int main() {

    int n , m;
    cin >> n >> m;

    char c;
    pair < int, int > start, end;

    // citire matrice si retinut pozitii
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            dist[i][j] = inf;
            cin >> c;
            if (c == '*') {
                obst[i][j] = 1;
            }
            if (c == 'D') {
                q.push({ i , j });
                dist[i][j] = 0;
            }
            if (c == 'I') {
                start = { i , j };
            }
            if (c == 'O') {
                end = { i , j };
            }
        }
    }

    // facem lee pornind din toti dragonii ca sursa pentru a determina distanta minima catre un dragon din fiecare pozitie a matricei
    while (!q.empty()) {
        pair < int, int > now = q.front();
        q.pop();
        for (int i = 0; i < 4; i++) {
            int x = now.first + dirx[i];
            int y = now.second + diry[i];

            if (x < 1 || x > n || y < 1 || y > m) {
                continue;
            }
            if (obst[x][y]) {
                continue;
            }
            if (dist[x][y] != inf) {
                continue;
            }
            dist[x][y] = dist[now.first][now.second] + 1;
            q.push({ x , y });
        }
    }

    //cautam binar raspunsul
    int st = 1, dr = dist[start.first][start.second]; // dr este distanta de pe pozitia initiala deoarece pozitia initiala se afla in orice traseu (de acolo pornim)
    int ans = -1;

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

        used[start.first][start.second] = 1;
        q.push(start);

        while (!q.empty()) {
            pair < int, int > now = q.front();
            q.pop();
            for (int i = 0; i < 4; i++) {
                int x = now.first + dirx[i];
                int y = now.second + diry[i];

                if (x < 1 || x > n || y < 1 || y > m) {
                    continue;
                }
                if (obst[x][y]) {
                    continue;
                }
                if (dist[x][y] < mij) { // nu ar mai fi mij minimul distantei de pe traseu
                    continue;
                }
                if (used[x][y]) {
                    continue;
                }
                used[x][y] = 1; // pot ajunge pe pozitia x y pornind de la start
                q.push({ x , y });
            }
        }

        if (used[end.first][end.second]) { // am reusit sa ajung pe pozitia de final mergand doar pe casute cu dist[i][j] >= mij
            st = mij + 1;
            ans = mij;
        }
        else { // nu am reusit sa ajung la final
            dr = mij - 1;
        }

        // resetez toata matricea de used (va fi folosita la pasul urmator)
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                used[i][j] = 0;
            }
        }
    }

    cout << ans;

    return 0;
}