Cod sursa(job #2483521)

Utilizator MoodyFaresFares Mohamad MoodyFares Data 29 octombrie 2019 20:59:12
Problema Barbar Scor 90
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.48 kb
#include <cstdio>
#include <queue>

using namespace std;

const int MAX_DIM = 1000;

struct Coord {
  int x;
  int y;
};

int n, m;
char a[1 + MAX_DIM + 1][1 + MAX_DIM + 1];
bool vis[1 + MAX_DIM][1 + MAX_DIM];
int dirLin[] = {-1, 1, 0, 0};
int dirCol[] = {0, 0, 1, -1};
int distMin[1 + MAX_DIM][1 + MAX_DIM];
Coord start, finish;

void surround() {
  for (int i = 0; i <= n + 1; i++)
    a[i][0] = a[i][m + 1] = '*';
  for (int j = 0; j <= m + 1; j++)
    a[0][j] = a[n + 1][j] = '*';
}

void build_distMin() {
  queue<Coord> q;
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      if (a[i][j] == 'D') {
        q.push({i, j});
        vis[i][j] = true;
      }
    }
  }

  while (!q.empty()) {
    Coord current = q.front();
    q.pop();

    for (int dir = 0; dir < 4; dir++) {
      int newX, newY;

      newX = current.x + dirLin[dir];
      newY = current.y + dirCol[dir];
      if (!vis[newX][newY] && a[newX][newY] != '*') {
        vis[newX][newY] = true;
        distMin[newX][newY] = distMin[current.x][current.y] + 1;
        q.push({newX, newY});
      }
    }
  }
}

void init_vis() {
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++)
      vis[i][j] = false;
  }
}

bool is_possible(int minDist) {
  init_vis();

  queue<Coord> q;
  q.push(start);
  vis[start.x][start.y] = true;
  while (!q.empty()) {
    Coord current = q.front();
    q.pop();

    for (int dir = 0; dir < 4; dir++) {
      int newX, newY;

      newX = current.x + dirLin[dir];
      newY = current.y + dirCol[dir];
      if (!vis[newX][newY] && (a[newX][newY] == '.' || a[newX][newY] == 'O') && distMin[newX][newY] >= minDist) {
        vis[newX][newY] = true;
        q.push({newX, newY});
      }
    }
  }

  return vis[finish.x][finish.y];
}

int main() {
  freopen("barbar.in", "r", stdin);
  freopen("barbar.out", "w", stdout);

  scanf("%d%d", &n, &m);
  surround();
  for (int i = 1; i <= n; i++) {
    getc(stdin);
    for (int j = 1; j <= m; j++) {
      a[i][j] = getc(stdin);
      if (a[i][j] == 'I')
        start = {i, j};
      else if (a[i][j] == 'O')
        finish = {i, j};
    }
  }

  build_distMin();

  int lft, rght, ans;
  lft = 1;
  rght = n + m;
  ans = -1;
  while (lft <= rght) {
    int med = (lft + rght) >> 1;

    if (is_possible(med)) {
      lft = med + 1;
      ans = med;
    } else {
      rght = med - 1;
    }
  }

  printf("%d\n", ans);
  return 0;
}