Cod sursa(job #2956666)

Utilizator nicu_ducalNicu Ducal nicu_ducal Data 20 decembrie 2022 10:01:13
Problema Barbar Scor 50
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.54 kb
#include <bits/stdc++.h>
using namespace std;

template <typename T> ostream& operator<<(ostream &os, const vector<T> &v) { os << '{'; string sep; for (const auto &x : v) os << sep << x, sep = ", "; return os << '}'; }
template <typename A, typename B> ostream& operator<<(ostream &os, const pair<A, B> &p) { return os << '(' << p.first << ", " << p.second << ')'; }
using i64 = long long int;

const int INF = INT_MAX, MOD = 1e9 + 7;
const long long LINF = LLONG_MAX;
const double EPS = 1e-9, PI = acos(-1);
const int dx[] = {0, 0, 0, -1, 1, -1, 1, 1, -1};
const int dy[] = {0, -1, 1, 0, 0, -1, 1, -1, 1};

struct Lee {
  vector<string> adj;
  vector<vector<bool>> marked;
  vector<vector<int>> closest_dragon;
  pair<int, int> in, out;
  int n, m;


  Lee(int _n = 0, int _m = 0) {
    init(_n, _m);
  }

  void init(int _n, int _m) {
    n = _n; m = _m;
    marked.resize(n);
    closest_dragon.resize(n);
    for (int i = 0; i < n; i++) {
      marked[i].resize(m, false);
      closest_dragon[i].resize(m, INF);
    }
  }

  void dragon_distances() {
    queue<pair<int, int>> q;
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++)
        if (adj[i][j] == 'D') {
          q.emplace(i, j);
          closest_dragon[i][j] = 0;
        }
    }

    while (not q.empty()) {
      pair<int, int> now = q.front();
      q.pop();

      for (int i = 1; i <= 4; i++) {
        pair<int, int> next = {now.first + dx[i], now.second + dy[i]};
        if (next.first < 0 or next.second < 0 or next.first >= n or next.second >= m) continue;
        if (adj[next.first][next.second] == '*') continue;
        if (closest_dragon[next.first][next.second] <= closest_dragon[now.first][now.second] + 1) continue;
        closest_dragon[next.first][next.second] = closest_dragon[now.first][now.second] + 1;
        q.push(next);
      }
    }
  }

  bool LeeBFS(int value) {
    for (int i = 0; i < n; i++)
      for (int j = 0; j < m; j++)
        marked[i][j] = false;

    queue<pair<int, int>> q;
    q.push(in);

    while (not q.empty()) {
      pair<int, int> now = q.front();
      q.pop();
//      printf("%d %d\n", now.first, now.second);
      marked[now.first][now.second] = true;

      for (int i = 1; i <= 4; i++) {
        pair<int, int> next = {now.first + dx[i], now.second + dy[i]};
        if (next.first < 0 or next.second < 0 or next.first >= n or next.second >= m) continue;
        if (adj[next.first][next.second] == '*' or adj[next.first][next.second] == 'D') continue;
        if (closest_dragon[next.first][next.second] < value) continue;
        if (marked[next.first][next.second]) continue;
        q.push(next);
      }
    }

    return marked[out.first][out.second];
  }

  int binary_search_distance(int lo, int hi) {
    int ans = -1;
    while (lo <= hi) {
      int mid = lo + (hi - lo) / 2;
      if (LeeBFS(mid)) {
        ans = mid;
        lo = mid + 1;
      } else
        hi = mid - 1;
    }

    return ans;
  }
};

int main() {
  ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
  /// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

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

  int N, M; cin >> N >> M;
  Lee lee(N, M);
  string row;

  for (int i = 0; i < N; i++) {
    cin >> row;
    lee.adj.push_back(row);
    for (int j = 0; j < M; j++) {
      if (row[j] == 'I')
        lee.in = {i, j};
      else if (row[j] == 'O')
        lee.out = {i, j};
    }
  }

  lee.dragon_distances();
  int ans = lee.binary_search_distance(1, lee.closest_dragon[lee.in.first][lee.in.second]);
  cout << ans;

  return 0;
}