Cod sursa(job #1492445)

Utilizator aimrdlAndrei mrdl aimrdl Data 27 septembrie 2015 19:16:18
Problema Barbar Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.63 kb
#include <stdio.h>
#include <queue>
#include <vector>
#include <algorithm>

#define IN -1
#define OUT -2
#define DRAGON 0
#define FREE -3
#define BLOCKED -4

using namespace std;

typedef struct {
	int i, j;
	int d;
} TPos;

typedef struct compare {
	bool operator () (const TPos a, const TPos b) {
		return a.d < b.d;
	}
} compare;

int R, C, Ii, Ij, m = 99999999, reached;
int M[1005][1005];
vector <TPos> H;

bool comp (TPos a, TPos b) {
	return (a.d < b.d) ? true : false;
}

void read() {
	scanf("%d %d\n", &R, &C);
	
	char buffer[1005];
	
	for (int i = 0; i < R; ++i) {
		fgets(buffer, 1005, stdin);
		for (int j = 0; j < C; ++j) {
			switch (buffer[j]) {
				case '.': M[i][j] = FREE; break;
				case 'D': M[i][j] = DRAGON; break;
				case '*': M[i][j] = BLOCKED; break;
				case 'O': M[i][j] = OUT; break; 
				case 'I': {
					M[i][j] = IN;
					Ii = i; Ij = j;
					break;
				}
				default: break;
			}
		}
	}
}

int findDist (int i, int j) {	
	int dist[1005][1005] = {{0}};
	dist[i][j] = 1;
	
	queue < pair <int, int> > Q;
	Q.push(make_pair(i, j));
	
	while (!Q.empty()) {
		auto c = Q.front();
		if (M[c.first][c.second] == DRAGON) return dist[c.first][c.second]-1;
		
		if (c.first > 0 && !dist[c.first-1][c.second] && M[c.first-1][c.second] > BLOCKED) {
			dist[c.first-1][c.second] = dist[c.first][c.second] + 1;
			Q.push(make_pair(c.first-1, c.second));
		}
		
		if (c.first < R-1 && !dist[c.first+1][c.second] && M[c.first+1][c.second] > BLOCKED) {
			dist[c.first+1][c.second] = dist[c.first][c.second] + 1;
			Q.push(make_pair(c.first+1, c.second));
		}
			
		if (c.second > 0 && !dist[c.first][c.second-1] && M[c.first][c.second-1] > BLOCKED) {
			dist[c.first][c.second-1] = dist[c.first][c.second] + 1;
			Q.push(make_pair(c.first, c.second - 1));
		}
		
		if (c.second < C-1 && !dist[c.first][c.second+1] && M[c.first][c.second+1] > BLOCKED) {
			dist[c.first][c.second+1] = dist[c.first][c.second] + 1;
			Q.push(make_pair(c.first, c.second + 1));
		}
		Q.pop();
	}
	
	return -999; //shouldn't happen
}

//find path with min dist d if possible
int bf (int d) {
	bool visited[1005][1005];
	visited[Ii][Ij] = true;
		
	queue < pair <int, int> > Q;
	Q.push(make_pair(Ii, Ij));
	
	while (!Q.empty()) {
		auto c = Q.front();
		Q.pop();
		if (M[c.first][c.second] == OUT) return 1;
		
		if (c.first && (M[c.first-1][c.second] >= d || M[c.first-1][c.second] == OUT) && !visited[c.first-1][c.second]) {
			Q.push(make_pair(c.first-1, c.second));
			visited[c.first-1][c.second] = true;
		}
		if (c.first < R-1 && (M[c.first+1][c.second] >= d || M[c.first+1][c.second] == OUT) && !visited[c.first+1][c.second]) {
			Q.push(make_pair(c.first+1, c.second));
			visited[c.first+1][c.second] = true;
		}
		if (c.second && (M[c.first][c.second-1] >= d || M[c.first][c.second-1] == OUT) && !visited[c.first][c.second-1]) {
			Q.push(make_pair(c.first, c.second-1));
			visited[c.first][c.second-1] = true;
		}
		if (c.second < C-1 && (M[c.first][c.second+1] >= d || M[c.first][c.second+1] == OUT) && !visited[c.first][c.second+1]) {
			Q.push(make_pair(c.first, c.second+1));
			visited[c.first][c.second+1] = true;
		}
	}
	
	return 0;
}

int maxdist (int max) {
	int l  = 0, r = max, mid;
	while (l < r) {
		mid = (l + r) / 2;
		if (bf(mid)) {
			l = mid;
		} else {
			r = mid;
		}
	}
	
	return mid;
}
	
			
		
			

int fillM () {
	int max = 0;
	for (int i = 0; i < R; ++i) {
		for (int j = 0; j < C; ++j) {
			if (M[i][j] == FREE) {
				M[i][j] = findDist(i, j);
				if (M[i][j] > max) max = M[i][j];
			}
		}
	}
	
	return max;
}

int main (void) {
	freopen("barbar.in", "r", stdin);
	freopen("barbar.out", "w", stdout);
	
	read();
	
	int max = fillM();
	
	printf("%d", maxdist(max));
	
	return 0;
}