Cod sursa(job #2017373)

Utilizator Stefan_RaduStefan Radu Stefan_Radu Data 31 august 2017 23:15:41
Problema Barbar Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.95 kb
#include <fstream>
#include <vector>
#include <queue>
#include <cmath>
 
using namespace std;
 
ifstream cin("barbar.in");
ofstream cout("barbar.out");
 
const int INF = 2e9;
 
int di[4] = {0, 0, 1, -1};
int dj[4] = {1, -1, 0, 0};
 
bool is_good(int i, int j, int n, int m) {
  return i >= 1 and j >= 1 and i <= n and j <= m;
}
 
void bfs(pair < int, int > poz, vector < vector < int > > &dist_drag, int n, int m) {
  queue < pair < int, int > > q;
 
  dist_drag[poz.first][poz.second] = 0;
  q.push(poz);
 
  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];
      int next_dist = dist_drag[cur.first][cur.second] + 1;
       
      if (!is_good(row, col, n, m)) continue;
      if (next_dist >= dist_drag[row][col]) continue;
 
      dist_drag[row][col] = next_dist;
      q.push({row, col});
    }
  }
}
 
void dfs(int min_dist, pair < int, int > me, pair < int, int > destination, int n, int m,
  bool &found_path, vector < string > &v, vector < vector < int > > &dist_drag, vector < vector < bool > > &used) {
 
  if (found_path) return;
  if (dist_drag[me.first][me.second] < min_dist or 
    v[me.first][me.second] == '*' or v[me.first][me.second] == 'D') {
    return;
  } 
 
  if (me == destination) {
    found_path = true;
    return;    
  }
 
  for (int i = 0; i < 4; i ++) {
    int row = me.first + di[i];
    int col = me.second + dj[i];
    if (!is_good(row, col, n, m)) continue;
    if (used[row][col]) continue;
 
    used[row][col] = true;
    dfs(min_dist, {row, col}, destination, n, m, found_path, v, dist_drag, used);
  }
}
 
void get_dist_drag(int n, int m, queue < pair < int, int > > &q, 
  vector < vector < int > > &dist_drag) {
 
  while (!q.empty()) {
    auto cur_drag = q.front();
    q.pop();
    bfs(cur_drag, dist_drag, n, m);
  }
}
 
int main(int argc, char const *argv[]) {
  int n, m;
  cin >> n >> m;
  vector < string > v (n + 1);
 
  for (int i = 1; i <= n; i ++) {
    cin >> v[i];
    v[i] = '*' + v[i];
  }
 
  queue < pair < int, int > > q;
  pair < int, int > me;
  pair < int, int > destination;
  for (int i = 1; i <= n; i ++) {  
    for (int j = 1; j <= m; j ++) {
      if (v[i][j] == 'D') {
        q.push({i, j});
      }
      else if (v[i][j] == 'I') {
        me = {i, j};
      }
      else if (v[i][j] == 'O') {
        destination = {i, j};
      }
    }
  }
 
  vector < vector < int > > dist_drag (n + 1, vector < int > (m + 1, INF));
  get_dist_drag(n, m, q, dist_drag);
 
  int min_dist = 0;
  int sol = -1;
  for (int i = log2(n + m + 1); i >= 0; i --) {
    if ((1 << i) > n + m + 1) continue;
    bool found_path = false;
    vector < vector < bool > > used(n + 1, vector < bool > (m + 1));
    used[me.first][me.second] = true;
    dfs(min_dist + (1 << i), me, destination, n, m, found_path, v, dist_drag, used);
 
    if (found_path) {
      min_dist += (1 << i);
      sol = min_dist;
    }
  }
 
  cout << sol << '\n';
 
  return 0;
}