Cod sursa(job #970838)

Utilizator toranagahVlad Badelita toranagah Data 7 iulie 2013 22:01:28
Problema Barbar Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.5 kb
#include <algorithm>
#include <fstream>
#include <iostream>
#include <queue>
#include <string>
#include <vector>
using namespace std;

struct Point {int x, y;};

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

const int MAX_N = 1005;
const int INF = 1 << 30;
const int dx[] = {0, 1, 0, -1};
const int dy[] = {1, 0, -1, 0};

int N, M;
Point SOURCE, DESTINATION;
int d[MAX_N][MAX_N]; 
bool visited[MAX_N][MAX_N];
queue<Point> q;
int answer;

void read_input();
void solve();
void print_output();
bool bfs(bool check = false, int min_val = 0);
inline bool is_bounded(int x, int y);

int main() {
  read_input();
  solve();
  print_output();
  return 0;
}

void read_input() {
  fin >> N >> M;
	fin.ignore();
  string row;
  for (int i = 0; i < N; ++i) {
    getline(fin, row);
    for (int j = 0; j < M; ++j) {
      if (row[j] == 'D') {
        d[i + 1][j + 1] = 0;
        q.push({i + 1, j + 1});
      } else if (row[j] == '*') {
				d[i + 1][j + 1] = -1;
			} else {
        d[i + 1][j + 1] = INF;
        if (row[j] == 'I') {
          SOURCE = {i + 1, j + 1};
        }
        if (row[j] == 'O') {
          DESTINATION = {i + 1, j + 1};
        }
      }
    }
  }
}

void solve() {
  bfs();
  q = queue<Point>();
	for (int i = 1; i <= N; ++i ) {
		for (int j = 1; j <= M; ++j) {
			cerr << d[i][j] << ' ';
		}
		cerr << endl;
	}
  
  int lo = 0, hi = N + M;
  while (lo <= hi) {
		int mid = lo + (hi - lo) / 2;
		if (bfs(true, mid)) {
			answer = lo;
			lo = mid + 1;
		} else {
			hi = mid - 1;
		}
	}

	if (!bfs(true, answer)) {
		answer = -1;
	}

}

void print_output() {
   fout << answer + 1;
}

bool bfs(bool check, int min_val) {
	if (check) {
		if (min_val > d[SOURCE.x][SOURCE.y]) return false;
    for (int i = 0; i <= N; ++i) {
			for (int j = 0; j <= M; ++j) {
				visited[i][j] = false;
			}
		}
		q = queue<Point>();
		q.push(SOURCE);
	}

	while (!q.empty()) {
    int x = q.front().x;
    int y = q.front().y;
		q.pop();

    for (int k = 0; k < 4; ++k) {
      int xx = x + dx[k];
      int yy = y + dy[k];
      if (is_bounded(xx, yy)) {
      	if (check) {
					if (d[xx][yy] >= min_val && !visited[xx][yy]) {
						if (xx == DESTINATION.x && yy == DESTINATION.y) {
							return true;
						}
						visited[xx][yy] = true;
						q.push({xx, yy});
					}
				} else {
					if (d[xx][yy] == INF) {
						d[xx][yy] = d[x][y] + 1;
						q.push({xx, yy});
					}
				}
			}
		}
	}
	return false;
}

inline bool is_bounded(int x, int y) {
	if (x < 1 || y < 1) return false;
	if (x > N || y > M) return false;
	return d[x][y] != -1;
}