Cod sursa(job #3242553)

Utilizator TeodorLuchianovTeo Luchianov TeodorLuchianov Data 12 septembrie 2024 16:37:52
Problema Barbar Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.06 kb
#include <fstream>
#include <queue>
#include <vector>
#include <algorithm>

using namespace std;

ifstream in("barbar.in");
ofstream out("barbar.out");

int const INF = 1e9+7;

struct Point {
  int x;
  int y;
};

Point start, stop;

int dirX[4] = {-1, 0, 1, 0};
int dirY[4] = {0, -1, 0, 1};

int const NMAX = 1000;
char mat[1 + NMAX][1 + NMAX];
int dist[1 + NMAX][1 + NMAX];
int active[1 + NMAX][1 + NMAX];
Point root[1 + NMAX][1 + NMAX];
int treeSize[1 + NMAX][1 + NMAX];
vector <Point> dungeon;
vector <Point> dragon;

bool isEqual(Point a, Point b) {
  return (a.x == b.x && a.y == b.y);
}

Point findRoot(Point node) {
  if(isEqual(node, root[node.x][node.y])) {
    return node;
  }
  root[node.x][node.y] = findRoot(root[node.x][node.y]);
  return root[node.x][node.y];
}

void connectNodes(Point a, Point b) {
  Point rootA = findRoot(a), rootB = findRoot(b);
  if(isEqual(rootA, rootB)) {
    return;
  }else {
    if(treeSize[rootA.x][rootA.y] < treeSize[rootB.x][rootB.y]) {
      root[rootA.x][rootA.y] = rootB;
      treeSize[rootB.x][rootB.y] += treeSize[rootA.x][rootA.y];
    }else {
      root[rootB.x][rootB.y] = rootA;
      treeSize[rootA.x][rootA.y] += treeSize[rootB.x][rootB.y];
    }
  }
}

bool compareDungeon(Point a, Point b) {
  return (dist[a.x][a.y] > dist[b.x][b.y]);
}

void BFS(int n, int m) {
  for(int i = 1;i <= n;i++) {
    for(int j = 1;j <= m;j++) {
      dist[i][j] = INF;
    }
  }
  queue <Point> q;
  for(int i = 0;i < dragon.size();i++) {
    Point temp = dragon[i];
    dist[temp.x][temp.y] = 0;
    q.push(temp);
  }
  while(!q.empty()) {
    Point from = q.front();
    q.pop();
    for(int dir = 0;dir < 4;dir++) {
      Point to = {from.x + dirX[dir], from.y + dirY[dir]};
      if(dist[to.x][to.y] == INF && mat[to.x][to.y] != '*') {
        dist[to.x][to.y] = dist[from.x][from.y] + 1;
        q.push(to);
      }
    }
  }
}

int main() {

  int n, m;
  in >> n >> m;
  for(int i = 1;i <= n;i++) {
    for(int j = 1;j <= m;j++) {
      in >> mat[i][j];
      if(mat[i][j] == 'O') {
        stop = {i, j};
      }else if(mat[i][j] == 'I') {
        start = {i, j};
      }else if(mat[i][j] == 'D') {
        dragon.push_back({i, j});
      }
      if(mat[i][j] != '*') {
        dungeon.push_back({i, j});
      }
      root[i][j] = {i, j};
    }
  }
  BFS(n, m);
  /*for(int i = 1;i <= n;i++) {
    for(int j = 1;j <= m;j++) {
      if(dist[i][j] == INF) {
        cout << "# ";
      }else {
        cout << dist[i][j] << ' ';
      }
    }
    cout << '\n';
  }*/
  sort(dungeon.begin(), dungeon.end(), compareDungeon);
  for(int i = 0;i < dungeon.size();i++) {
    Point from = dungeon[i];
    active[from.x][from.y] = true;
    for(int dir = 0;dir < 4;dir++) {
      Point to = {from.x + dirX[dir], from.y + dirY[dir]};
      if(active[to.x][to.y]) {
        connectNodes(from, to);
      }
    }
    if(isEqual(findRoot(start), findRoot(stop))) {
      out << dist[from.x][from.y] << '\n';
      return 0;
    }
  }
  out << -1;
  return 0;
}