Cod sursa(job #2292376)

Utilizator ApostolIlieDanielApostol Daniel ApostolIlieDaniel Data 29 noiembrie 2018 14:22:56
Problema Barbar Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.42 kb

#include <bits/stdc++.h>

using namespace std;

FILE *fin = fopen ("barbar.in", "r"), *fout = fopen ("barbar.out", "w");

struct coord {int x; int y;};

const int MAXN = 1000, INF = 1e9;

int viz[MAXN + 1][MAXN + 1];
int dl[4] = {0, 0, -1, 1};
int dc[4] = {-1, 1, 0, 0};
int nr;
int n, m;
coord q[MAXN * MAXN + 1];
coord dragon[MAXN * MAXN + 1];
int a[MAXN + 1][MAXN + 1];
int xstart, ystart, xend, yend;
int dist[MAXN + 1][MAXN + 1];
void precalculare () {
  int i, b, e, d;
  // se propaga zonele pe unde nu se poate trece
  memset (dist, 0, sizeof (dist));
  b = 0;
  e = -1;
  for (i = 1; i <= nr; i++) {
    e++;
    q[e] = dragon[i];
    dist[q[e].x][q[e].y] = 1;
  }
  while (b <= e) {
    coord nod = q[b++];
    for (d = 0; d < 4; d++) {
      coord nou;
      nou.x = nod.x + dl[d];
      nou.y = nod.y + dc[d];
      if (nou.x > 0 && nou.x <= n && nou.y > 0 && nou.y <= m && dist[nou.x][nou.y] == 0 && a[nou.x][nou.y] != 1) {
        dist[nou.x][nou.y] = dist[nod.x][nod.y] + 1;
        q[++e] = nou;
      }
    }
  }
}

void dfs (int x, int y, int k) {
  int d;
  viz[x][y] = -1;
  for (d = 0; d < 4; d++) {
    int xn = x + dl[d];
    int yn = y + dc[d];
    if (xn > 0 && xn <= n && yn > 0 && yn <= m && viz[xn][yn] == 0 && dist[xn][yn] > k && a[xn][yn] != 1)
      dfs (xn, yn, k);
  }
}

bool check (int k) {
  // se vede daca se poate ajunge din start in end
  memset (viz, 0, sizeof (viz));
  if (dist[xstart][ystart] > k)
    dfs (xstart, ystart, k);
  if (viz[xend][yend] == -1)
    return true;
  return false;
}

char s[MAXN + 1];

int main() {
  int i, j, st, dr, sol, mij;
  fscanf (fin, "%d%d", &n, &m);
  for (i = 1; i <= n; i++) {
    fscanf (fin, "%s", &s);
    // decriptam
    for (j = 1; j <= m; j++) {
      if (s[j - 1] == '*')
        a[i][j] = 1;
      if (s[j - 1] == 'D') {
        dragon[++nr].x = i;
        dragon[nr].y = j;
      }
      if (s[j - 1] == 'I') {
        xstart = i;
        ystart = j;
      }
      if (s[j - 1] == 'O') {
        xend = i;
        yend = j;
      }
    }
  }
  precalculare ();
  // se poate cauta binar raspunsul
  st = 0;
  dr = min (n, m);
  sol = -1;
  while (st <= dr) {
    mij = (st + dr) / 2;
    if (check (mij) == true) {
      st = mij + 1;
      sol = mij;
    }
    else {
      dr = mij - 1;
    }
  }
  fprintf (fout, "%d\n", sol);
  fclose (fin);
  fclose (fout);
  return 0;
}