Cod sursa(job #29414)

Utilizator sima_cotizoSima Cotizo sima_cotizo Data 9 martie 2007 12:28:55
Problema Barbar Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.08 kb
// a doua sursa, avand in vedere ca prima a fost facuta "profesionist"

#include <cstdio>
#define FIN "barbar.in"
#define FOUT "barbar.out"
#define MAX 1000
#define inf 0x3f3f3f
#define newx P->x+dx[i]
#define newy P->y+dy[i]
#define actx P->x
#define acty P->y

char A[MAX][MAX], B[MAX][MAX];
long dist[MAX][MAX];
long N,M, max, ok=0;
long dx[] = {1,0,-1,0},
	 dy[] = {0,1,0,-1};


struct point {
	long x, y;
	point *l;
} I, O, *P=0, *U;

void init() {
	long i,j;
	for (i=1; i<=N; ++i)
		for (j=1; j<=M; ++j)
			dist[i][j] = inf;
}

void add(long x, long y) {
	if (P==0) {
		P = new point;
		U = P;
		P -> x = x;
		P -> y = y;
		P -> l = 0;
		return;
	}
	point *tmp = new point;
	tmp -> l = 0;
	tmp -> x = x;
	tmp -> y = y;
	U -> l = tmp;
	U=tmp;
}

void afla_distantele() {
	long i;
	for ( ; P; P= P->l ) {
		for (i=0; i<4; ++i)
			if ( dist[newx][newy] > dist[actx][acty]+1 ) {
				add(newx, newy);
				dist[newx][newy] = dist[actx][acty]+1;
			}
	}
}

int lee(long x) { // lee prin casute cu valoarea minima x
	long i, j;
	for (i=1; i<=N; ++i) 
		for (j=1; j<=M; ++j)
			B[i][j] = 0;

	add(I.x, I.y);
	B[I.x][I.y] = 1;
	for (; P; P=P->l) {
		for (i=0; i<4; ++i) 
			if ( dist[newx][newy] >= x && B[newx][newy] == 0) {
				add(newx,newy);
				B[newx][newy] = 1;
			}
		if ( B[O.x][O.y] ) 
			return 1;
	}

	return B[O.x][O.y]==1;
}

int main(){ 
	char buf[MAX]; long i,j;

	freopen(FIN, "r", stdin);
	scanf("%ld %ld", &N, &M);
	init();
	for (i=1; i<=N; ++i) {
		fgets(buf, 1004, stdin);
		for (j=1; j<=M; ++j) {
			A[i][j] = buf[j];
			if ( A[i][j] == 'I' )
				I.x = i, I.y = j;
			if ( A[i][j] == 'O' )
				O.x = i, O.y = j;
			if ( A[i][j] == 'D' ) {
				add(i,j);
				dist[i][j] = 0;
			}
			if ( A[i][j]=='*' )
				dist[i][j] = -1;
		}
	}
	fclose(stdin);

	afla_distantele();
	max = 0;
	for (i=1; i<=N; ++i)
		for (j=1; j<=M; ++j)
			max = (max < dist[i][j]) ? dist[i][j] : max;

	long st = 0, dr = max+1, m, r;
	while ( st<dr ) {
		m = (st+dr) / 2;
		if ( lee(m) ) {
			st = m+1;
			ok = 1; r=m;
		}
		else
			dr = m-1;
	}

	freopen(FOUT, "w", stdout);
	printf("%ld\n",(ok) ? r : -1);
	fclose(stdout);

	return 0;
}