Cod sursa(job #2663831)

Utilizator cristi_macoveiMacovei Cristian cristi_macovei Data 27 octombrie 2020 13:44:32
Problema Barbar Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.43 kb
#include <iostream>
#include <fstream>
#include <queue>
#include <cstring>

const int NMAX = 1e3;

const int di[] = {-1, 0, 1,  0};
const int dj[] = { 0, 1, 0, -1};
// N, E, S, W

int n, m;
std::pair<int, int> start, end;
std::vector<std::pair<int, int>> dragons;

char a[1 + NMAX][1 + NMAX];
int dist[1 + NMAX][1 + NMAX];
bool vis[1 + NMAX][1 + NMAX];

std::queue<std::pair<int, int>> q;

void read() {
  std::ifstream in("barbar.in");

  in >> n >> m;
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= m; ++j) {
      in >> a[i][j];

      if (a[i][j] == 'D')
        dragons.emplace_back(i, j);
      else if (a[i][j] == 'I')
        start = {i, j};
      else if (a[i][j] == 'O')
        end = {i, j};
    }
  }

  in.close();
}

inline bool isAccessible (const std::pair<int, int>& pos) {
  return 1 <= pos.first && pos.first <= n && 1 <= pos.second && pos.second <= m && a[pos.first][pos.second] != '*';
}

void dragonsBfs() {
  memset(dist, -1, sizeof(dist));

  for (auto& dragon: dragons) {
    q.push(dragon);
    dist[dragon.first][dragon.second] = 0;
  }

  while (!q.empty()) {
    auto pos = q.front();
    q.pop();

    for (int dir = 0; dir < 4; ++dir) {
      std::pair<int, int> newPos = {pos.first + di[dir], pos.second + dj[dir]};

      if (isAccessible(newPos) && dist[newPos.first][newPos.second] == -1) {
        dist[newPos.first][newPos.second] = dist[pos.first][pos.second] + 1;
        q.push(newPos);
      }
    }
  }
}

bool checkBfs(int targetDist) {
  if (dist[start.first][start.second] < targetDist)
    return false;

  while (!q.empty())
    q.pop();
  memset(vis, 0, sizeof(vis));

  q.push(start);
  vis[start.first][start.second] = true;

  while (!q.empty()) {
    auto pos = q.front();
    q.pop();

    for (int dir = 0; dir < 4; ++dir) {
      std::pair<int, int> newPos = {pos.first + di[dir], pos.second + dj[dir]};

      if (isAccessible(newPos) && !vis[newPos.first][newPos.second] && dist[newPos.first][newPos.second] >= targetDist) {

        if (newPos == end)
          return true;

        q.push(newPos);
        vis[newPos.first][newPos.second] = true;
      }
    }
  }

  return false;
}

int main() {
  read();
  dragonsBfs();

  int left = 0, right = n * m, mid, last = -1;
  while (left <= right) {
    mid = (left + right) >> 1;

    if (checkBfs(mid)) {
      last = mid;
      left = mid + 1;
    } else
      right = mid - 1;
  }

  std::ofstream out("barbar.out");
  out << last << '\n';

  out.close();
  return 0;
}