Cod sursa(job #2075976)

Utilizator dariusdariusMarian Darius dariusdarius Data 25 noiembrie 2017 21:45:38
Problema Barbar Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.36 kb
#include <fstream>
#include <iostream>
#include <queue>
#include <vector>

#include <cstring>

const int MAX_N = 1005;
const int dx[] = {0, 1, 0, -1};
const int dy[] = {-1, 0, 1, 0};

int n, m;
bool visited[MAX_N][MAX_N];
bool walls[MAX_N][MAX_N];
int dragon_dist[MAX_N][MAX_N];

inline bool in(int x, int y) {
    return 0 <= x && x < n && 0 <= y && y < m;
}

bool CanTravel(int dist, std::pair<int, int> start, std::pair<int, int> stop) {
    if (dragon_dist[start.first][start.second] < dist) {
        return false;
    }
    std::queue< std::pair<int, int> > q;
    memset(visited, 0, sizeof visited);
    q.push(start);
    visited[start.first][start.second] = true;
    while (!q.empty()) {
        auto pos = q.front();
        q.pop();
        for (int d = 0; d < 4; ++ d) {
            std::pair<int, int> new_pos = {pos.first + dx[d], pos.second + dy[d]};
            if (0 > new_pos.first || n <= new_pos.first || 0 > new_pos.second || m <= new_pos.second) {
                continue;
            }
            if (!visited[new_pos.first][new_pos.second] && !walls[new_pos.first][new_pos.second] && dragon_dist[new_pos.first][new_pos.second] >= dist) {
                if (new_pos == stop) {
                    return true;
                }
                visited[new_pos.first][new_pos.second] = true;
                q.push(new_pos);
            }
        }
    }
    return false;
}

void bfs(const std::vector< std::pair<int, int> > &dragons) {

}

int main()
{
    std::ifstream cin("barbar.in");
    std::ofstream cout("barbar.out");
    char line[MAX_N];
    cin >> n >> m;
    std::pair<int, int> start, stop;
    std::queue< std::pair<int, int> > q;
    for (int i = 0; i < n; ++ i) {
        for (int j = 0; j < m; ++ j) {
            dragon_dist[i][j] = 1000000000;
        }
    }
    for (int i = 0; i < n; ++ i) {
        cin >> line;
        for (int j = 0; j < m; ++ j) {
            if (line[j] == '.') {
                continue;
            }
            if (line[j] == 'D') {
                dragon_dist[i][j] = 0;
                q.push({i, j});
                continue;
            }
            if (line[j] == '*') {
                walls[i][j] = true;
                continue;
            }
            if (line[j] == 'I') {
                start = {i, j};
            } else {
                stop = {i, j};
            }
        }
    }
    while (!q.empty()) {
        auto pos = q.front();
        q.pop();
        for (int d = 0; d < 4; ++ d) {
            std::pair<int, int> new_pos = {pos.first + dx[d], pos.second + dy[d]};
            if (0 > new_pos.first || n <= new_pos.first || 0 > new_pos.second || m <= new_pos.second) {
                continue;
            }
            if (dragon_dist[new_pos.first][new_pos.second] == 1000000000 && !walls[new_pos.first][new_pos.second]) {
                dragon_dist[new_pos.first][new_pos.second] = dragon_dist[pos.first][pos.second] + 1;
                q.push(new_pos);
            }
        }
    }
    int left = 0, right = n * m, best = -1;
    while (left <= right) {
        int middle = (left + right) / 2;
        if (CanTravel(middle, start, stop)) {
            best = middle;
            left = middle + 1;
        } else {
            right = middle - 1;
        }
    }
    cout << best << "\n";
    return 0;
}