Cod sursa(job #1027326)

Utilizator razvan9310FMI - Razvan Damachi razvan9310 Data 12 noiembrie 2013 18:37:32
Problema Barbar Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.99 kb
#include <iostream>
#include <fstream>
#include <queue>
#define MAXSIZE 1001
using namespace std;

class punct {
  public:
    int x, y;

    punct(const int &X = 0, const int &Y = 0): x(X), y(Y) {
    }

    bool operator ==(const punct &comp) {
      return (x == comp.x && y == comp.y);
    }
}I, O;

int R, C, dist[MAXSIZE][MAXSIZE];
char mat[MAXSIZE][MAXSIZE];
queue<punct> que;

void input() {
  ifstream in("barbar.in");
  in >> R >> C;

  for (int i = 0; i < R; ++i) {
    for (int j = 0; j < C; ++j) {
      dist[i][j] = 1 << 30;
      in >> mat[i][j];

      if (mat[i][j] == 'D') {
        que.push(punct(j, i));
        dist[i][j] = 0;
      } else {
        if (mat[i][j] == 'I') {
          I.x = j;
          I.y = i;
        } else {
          if (mat[i][j] == 'O') {
            O.x = j;
            O.y = i;
          }
        }
      }
    }
  }
  in.close();
}

bool validPosition(const punct &p) {
  return (p.x >= 0 && p.x < C && p.y >= 0 && p.y < R);
}

void generateDist() {
  while (!que.empty()) {

    punct next = que.front();
    que.pop();

    punct up(next.x, next.y + 1), right(next.x + 1, next.y), down(next.x, next.y - 1), left(next.x - 1, next.y);
    if (validPosition(up) && mat[up.y][up.x] != 'D' && mat[up.y][up.x] != '*' && dist[up.y][up.x] > 1 + dist[next.y][next.x]) {
      que.push(up);
      dist[up.y][up.x] = 1 + dist[next.y][next.x];
    }
    if (validPosition(right) && mat[right.y][right.x] != 'D' && mat[right.y][right.x] != '*' && dist[right.y][right.x] > 1 + dist[next.y][next.x]) {
      que.push(right);
      dist[right.y][right.x] = 1 + dist[next.y][next.x];
    }
    if (validPosition(down) && mat[down.y][down.x] != 'D' && mat[down.y][down.x] != '*' && dist[down.y][down.x] > 1 + dist[next.y][next.x]) {
      que.push(down);
      dist[down.y][down.x] = 1 + dist[next.y][next.x];
    }
    if (validPosition(left) && mat[left.y][left.x] != 'D'  && mat[left.y][left.x] != '*' & dist[left.y][left.x] > 1 + dist[next.y][next.x]) {
      que.push(left);
      dist[left.y][left.x] = 1 + dist[next.y][next.x];
    }
  }
}

int getMaxDist() {
  // intai cautam distanta maxima:
  int max_dist = 0;
  for (int i = 0; i < R; ++i) {
    for (int j = 0; j < C; ++j) {
      if (max_dist < dist[i][j]) {
        max_dist = dist[i][j];
      }
    }
  }

  return max_dist;
}

bool seen[MAXSIZE][MAXSIZE];

bool findPath(const int &distanta) {
  queue<punct> coada;
  coada.push(I);

  for (int i = 0; i < R; ++i) {
    for (int j = 0; j < C; ++j) {
      seen[i][j] = 0;
    }
  }

  while (!coada.empty()) {

    punct next = coada.front();
    seen[next.y][next.x] = 1;
    if (next == O) {
      return true;
    }
    coada.pop();
    punct up(next.x, next.y + 1), right(next.x + 1, next.y), down(next.x, next.y - 1), left(next.x - 1, next.y);

    if (validPosition(up) && !seen[up.y][up.x] && mat[up.y][up.x] != 'D' && mat[up.y][up.x] != '*' && dist[up.y][up.x] >= distanta) {
      coada.push(up);
    }

    if (validPosition(right) && !seen[right.y][right.x] && mat[right.y][right.x] != 'D' && mat[right.y][right.x] != '*' && dist[right.y][right.x] >= distanta) {
      coada.push(right);
    }

    if (validPosition(down) && !seen[down.y][down.x] && mat[down.y][down.x] != 'D' && mat[down.y][down.x] != '*' && dist[down.y][down.x] >= distanta) {
      coada.push(down);
    }

    if (validPosition(left) && !seen[left.y][left.x] && mat[left.y][left.x] != 'D' && mat[left.y][left.x] != '*' && dist[left.y][left.x] >= distanta) {
      coada.push(left);
    }
  }

  return false;
}

void binSearch(const int &left, const int &right, int &best) {
  if (left > right) {
    return;
  }

  int mid = left + (right - left) / 2;
  if (findPath(mid) == true) {
    best = mid;
    binSearch(mid + 1, right, best);
  } else {
    binSearch(left, mid - 1, best);
  }
}

int solve() {
  generateDist();
  int max_dist = getMaxDist();
  int best = -1;
  binSearch(0, max_dist, best);

  return best;
}

void output() {
  ofstream out("barbar.out");
  out << solve();
  out.close();
}

int main() {
  input();
  output();
  return 0;
}