Cod sursa(job #2713322)

Utilizator lucamLuca Mazilescu lucam Data 27 februarie 2021 18:17:10
Problema Barbar Scor 40
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.6 kb
#include <fstream>
#include <queue>
#include <algorithm>

std::ifstream in("barbar.in");
std::ofstream out("barbar.out");

const int dy[] = {-1, 0, 0, 1};
const int dx[] = {0, -1, 1, 0};
const int N = 1000;

int r, c;

bool map[N + 2][N + 2], visited[N + 2][N + 2];
int min_distances[N + 2][N + 2];
int max_distance = -1;
char line[N + 1];
struct Pos {
    int y, x;
};
Pos start, finish;
std::queue<Pos> q;

void input() {
    in >> r >> c;
    for (int i = 0; i < r; ++i) {
        in >> line;
        for (int j = 0; j < c; ++j) {
            switch (line[j]) {
            case 'D':
                q.push({i + 1, j + 1});
                break;
            case '*':
                map[i + 1][j + 1] = true;
                break;
            case 'I':
                start = {i + 1, j + 1};
                break;
            case 'O':
                finish = {i + 1, j + 1};
            }
        }
    }
}

void pad() {
    for (int i = 0; i <= r + 1; ++i) {
        map[i][0] = map[i][c + 1] = true;
    }
    for (int j = 0; j <= c + 1; ++j) {
        map[0][j] = map[r + 1][j] = true;
    }
}

void find_distances() {
    while (!q.empty()) {
        Pos cur = q.front();
        q.pop();
        for (int i = 0; i < 4; ++i) {
            int y = cur.y + dy[i], x = cur.x + dx[i];
            if (!map[y][x] && min_distances[y][x] == 0) {
                min_distances[y][x] = min_distances[cur.y][cur.x] + 1;
                if (min_distances[y][x] > max_distance) {
                    max_distance = min_distances[y][x];
                }
                q.push({y, x});
            }
        }
    }
}

void clear_visited() {
    for (int i = 1; i <= r; ++i) {
        for (int j = 1; j <= c; ++j) {
            visited[i][j] = false;
        }
    }
}

bool try_path(int min_distance) {
    clear_visited();
    q = {};
    q.push(start);
    while (!q.empty()) {
        Pos cur = q.front();
        q.pop();
        visited[cur.y][cur.x] = true;
        for (int i = 0; i < 4; ++i) {
            int y = cur.y + dy[i], x = cur.x + dx[i];
            if (!map[y][x] && !visited[y][x] && min_distances[y][x] >= min_distance) {
                if (y == finish.y && x == finish.x) {
                    return true;
                }
                q.push({y, x});
            }
        }
    }
    return false;
}

int solve_max() {
    int l = 1, r = max_distance + 1;
    while (l + 1 < r) {
        int m = (l + r) / 2;
        if (try_path(m)) {
            l = m;
        }
        else {
            r = m;
        }
    }
    return l;
}

int main() {
    input();
    pad();
    find_distances();
    out << solve_max() << '\n';
}