Mai intai trebuie sa te autentifici.

Cod sursa(job #2017404)

Utilizator Stefan_RaduStefan Radu Stefan_Radu Data 1 septembrie 2017 07:21:04
Problema Barbar Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.44 kb
#include <fstream>
#include <vector>
#include <queue>
#include <cmath>
  
using namespace std;
  
ifstream cin("barbar.in");
ofstream cout("barbar.out");
  
const int INF = 2e9;
const int MAX = 1005;
  
int di[4] = {0, 0, 1, -1};
int dj[4] = {1, -1, 0, 0};

bool walled[MAX][MAX];
int dist_drag[MAX][MAX];
bool used[MAX][MAX];

/*vector < vector < bool > > walled(MAX, vector < bool > (MAX));
vector < vector < int > > dist_drag(MAX, vector < int > (MAX, INF));
vector < vector < bool > > used(MAX, vector < bool > (MAX));*/

void init(int n, int m) {
  for (int i = 1; i <= n; i ++) {
    for (int j = 1; j <= m; j ++) {
      dist_drag[i][j] = INF;
    }
  }
}
  
bool is_good(int i, int j, int n, int m) {
  return i >= 1 and j >= 1 and i <= n and j <= m;
}

void read(int n, int m, pair < int, int > &me, pair < int, int > &dest, queue < pair < int, int > > &drags) {

  for (int i = 1; i <= n; i ++) {
    for (int j = 1; j <= m; j ++) {
      char c;
      cin >> c;
      if (c == 'I') {
        me = {i, j};
      }
      else if (c == 'O') {
        dest = {i, j};
      }
      else if (c == 'D') {
        drags.push({i, j});
      }
      else if (c == '*') {
        walled[i][j] = true;
      }
    }
  }
}

void complete (pair < int, int > dragon, int n, int m, int &pure_max_dist) {
  queue < pair < int, int > > q;

  dist_drag [dragon.first][dragon.second] = 0;
  walled[dragon.first][dragon.second] = true;
  q.push(dragon);

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

    for (int i = 0; i < 4; i ++) {
      int row = cur.first + di[i];
      int col = cur.second + dj[i];

      if (!is_good(row, col, n, m)) continue;
      if (walled[row][col]) continue;
      if (dist_drag[row][col] <= dist_drag[cur.first][cur.second] + 1) continue;
      dist_drag[row][col] = dist_drag[cur.first][cur.second] + 1;
      pure_max_dist = max (pure_max_dist, dist_drag[row][col]);
      q.push({row, col});
    }
  }
}

void reset(int n, int m) {
  for (int i = 1; i <= n; i ++) {
    for (int j = 1; j <= m; j ++) {
      used[i][j] = false;
    }
  }
}

bool found_path(int min_dist, pair < int, int > me, pair < int, int > dest, int n, int m) {
  reset(n, m);

  queue < pair < int, int > > q;
  
  if (dist_drag[me.first][me.second] >= min_dist) {
    q.push(me);
    used[me.first][me.second] = true;  
  }

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

    for (int i = 0; i < 4; i ++) {
      int row = cur.first + di[i];
      int col = cur.second + dj[i];
      
      if (used[row][col])continue;
      if (!is_good(row, col, n, m)) continue;
      if (walled[row][col]) continue;
      if (dist_drag[row][col] < min_dist) continue;
      if (dest == make_pair(row, col)) return true;
      used[row][col] = true;

      q.push({row, col});
    }
  }

  return false;
}

int main(int argc, char const *argv[]) {

  int n, m;
  cin >> n >> m;
  init(n ,m);
  
  queue < pair < int, int > > drags;
  pair < int, int > me;
  pair < int, int > dest;

  read(n , m, me, dest, drags);
  
  int pure_max_dist = -1;
  while (!drags.empty()) {
    complete(drags.front(), n, m, pure_max_dist);
    drags.pop();
  }

  int sol = -1;
  int ans = 0;

  for (int bit = log2(n + m + 1); bit >= 0; bit --) {
    if ((1 << bit) > n + m + 1) continue;
    if ((1 << bit) > pure_max_dist) continue;

    if (found_path(ans + (1 << bit), me, dest, n, m)) {
      ans += (1 << bit);
      sol = ans;
    }
  }

  cout << sol << '\n';

  return 0;
}