Cod sursa(job #1800565)

Utilizator mouse_wirelessMouse Wireless mouse_wireless Data 7 noiembrie 2016 21:34:25
Problema Barbar Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.53 kb
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;

#ifdef INFOARENA
#define ProblemName "barbar"
#endif

#define MCONCAT(A, B) A B
#ifdef ProblemName
#define InFile MCONCAT(ProblemName, ".in")
#define OuFile MCONCAT(ProblemName, ".out")
#else
#define InFile "fis.in"
#define OuFile "fis.out"
#endif

#define MAXN 1100
typedef pair<int, int> square;

char M[MAXN][MAXN];
int R, C;
int prec[MAXN][MAXN];
char viz[MAXN][MAXN];
int entrance[2], outway[2];
queue<square> Q;

inline char isEmpty(int i, int j) {
	return (M[i][j] != 'D' && M[i][j] != '#');
}

void BFSprec() {
	memset(prec, 0, sizeof(prec));
	memset(viz, 0, sizeof(viz));
	for (int i = 0; i < R; ++i)
	for (int j = 0; j < C; ++j)
	if (M[i][j] == 'D') {
		Q.push(make_pair(i, j));
		viz[i][j] = 1;
	}
	while (!Q.empty()) {
		pair<int, int> t = Q.front();
		Q.pop();
		for (int i = -1; i <= 1; ++i)
		for (int j = -1; j <= 1; ++j) {
			if (i == 0 && j == 0)
				continue;
			int x = t.first + i, y = t.second + j;
			if (x < 0 || x >= R || y < 0 || y >= C)
				continue;
			if (!isEmpty(x, y))
				continue;
			if (viz[x][y])
				continue;
			prec[x][y] = prec[t.first][t.second] + 1;
			viz[x][y] = 1;
			Q.push(make_pair(x, y));
		}
	}
}

char DFS(int t1, int t2, int ans) {
	viz[t1][t2] = 1;
	if (t1 == outway[0] && t2 == outway[1])
		return 1;
	for (int i = -1; i <= 1; ++i)
	for (int j = -1; j <= 1; ++j) {
		if (i == 0 && j == 0)
			continue;
		int x = t1 + i, y = t2 + j;
		if (x < 0 || x >= R || y < 0 || y >= C)
			continue;
		if (!isEmpty(x, y))
			continue;
		if (viz[x][y])
			continue;
		if (prec[x][y] > ans)
			continue;
		if (DFS(x, y, ans))
			return 1;
	}
	return 0;
}

char check(int ans) {
	memset(viz, 0, sizeof(viz));
	return DFS(entrance[0], entrance[1], ans);
}

int binarySearch() {
	BFSprec();
	int left = 1, right = MAXN;
	int found = -1;
	while (left <= right) {
		int mid = ((left + right) >> 1);
		if (check(mid)) {
			right = mid - 1;
			found = mid;
		}
		else
			left = mid + 1;
	}
	return found;
}

void readInput() {
	scanf("%d%d", &R, &C);
	for (int i = 0; i < R; ++i)
	for (int j = 0; j < C; ++j) {
		scanf(" %c", &M[i][j]);
		if (M[i][j] == 'I')
			entrance[0] = i, entrance[1] = j;
		else if (M[i][j] == 'O')
			outway[0] = i, outway[1] = j;
	}
}

int main() {
	freopen(InFile, "r", stdin);
	freopen(OuFile, "w", stdout);
	readInput();
	printf("%d\n", binarySearch());
	return 0;
}