Cod sursa(job #2017379)

Utilizator Stefan_RaduStefan Radu Stefan_Radu Data 31 august 2017 23:33:53
Problema Barbar Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.18 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};
vector < vector < bool > > used(MAX, vector < bool > (MAX));
  
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, vector < string > &v, 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;
      if (v[row][col] == 'D' or v[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) {
  
  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);
  }
}
  
void get_dist_drag(int n, int m, queue < pair < int, int > > &q, 
  vector < vector < int > > &dist_drag, vector < string > &v) {
  
  while (!q.empty()) {
    auto cur_drag = q.front();
    q.pop();
    bfs(cur_drag, dist_drag, v, 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, v);
  
  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;
    for (int j = 1; j <= n; j ++) {
      for (int k = 1; k <= m; k ++) {
        used[j][k] = false;
      }
    }
    
    used[me.first][me.second] = true;
    dfs(min_dist + (1 << i), me, destination, n, m, found_path, v, dist_drag);
    
    if (found_path) {
      min_dist += (1 << i);
      sol = min_dist;
    }
  }
  
  cout << sol << '\n';
  
  return 0;
}