Cod sursa(job #27824)

Utilizator sima_cotizoSima Cotizo sima_cotizo Data 7 martie 2007 09:42:03
Problema Barbar Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.79 kb
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
#define FIN "barbar.in"
#define FOUT "barbar.out"
#define MAX 1001
#define BIG_ONE 10000002

struct point
{
	long x, y, v;	
};

long R, C;
char A[MAX][MAX];
long V[MAX][MAX];
long B[MAX][MAX];

point mv[4] = {{-1,0},{1,0},{0,1},{0,-1}}; // vector of moves
queue <point> D;
point I, O;
long answer=0;

void read_data()
{
	long i, j;
	
	freopen(FIN, "r", stdin);
	scanf("%ld %ld", &R, &C);
	for (i=0; i<R; ++i)
		for (j=0; j<C; ++j)
		{
			scanf("%c", A[i]+j);
            while ( A[i][j]=='\n' && !feof(stdin) ) scanf("%c", A[i]+j);
			if ( A[i][j]=='D' )  // dragon - queue
			{
				point tmp;
				tmp.x = i; tmp.y = j; tmp.v = 0;
				D.push(tmp);
			}
			if ( A[i][j]=='I' ) // initial point
			{
				I.x = i;
				I.y = j;
			}
			if ( A[i][j]=='O' )
			{
				O.x = i;
				O.y = j;
			}
		}
	fclose(stdin);
}

void debug();

void solve()
{
	long i, j, mx=0;
	for (i=0; i<R; ++i)
		for (j=0; j<C; ++j)
			V[i][j]= BIG_ONE ;
		
	// expand all the dragons with a fill-based procedure, optimized with a queue (D)
	while ( !D.empty() )
	{
		point tmp = D.front();
//		printf("%ld %ld\n", tmp.x, tmp.y);
		V[ tmp.x ][ tmp.y ] = tmp.v;
		for (i=0; i<4; ++i)
		{
			point next;
			next.x = tmp.x + mv[i].x; next.y = tmp.y + mv[i].y;
			if ( next.x>=0 && next.x<R && next.y>=0 && next.y<C )
     			if ( V[ next.x ][ next.y ] > tmp.v + 1 && A[ next.x ][ next.y ]!='*')
	     		{
		     		V[ next.x ][ next.y ] = next.v = tmp.v + 1;
					if ( tmp.v+1>mx ) mx = tmp.v+1;
			     	D.push(next);
     			}
		}
		D.pop();
	}

	// binary search of x -> minimum, where x is the smallest value on the path
	long l=0, r=mx;
	while ( l<=r )
	{
		long m = (l+r)/2;
		long ok=1;
		memset(B, 0, sizeof(B));

		while ( !D.empty() ) D.pop();
		// same fill procedure;
		D.push(I);
		while ( !D.empty() && ok )
		{
			point tmp = D.front();
//			printf("%ld %ld\n", tmp.x, tmp.y);
			B[tmp.x][tmp.y]=1;
			for (i=0; i<4; ++i)
			{
				point next;
				next.x = tmp.x + mv[i].x; next.y = tmp.y + mv[i].y;
				if ( next.x>=0 && next.x<R && next.y>=0 && next.y<C )
					if ( V[next.x][next.y]>=m && !B[next.x][next.y] && A[next.x][next.y]!='*' )
					{
						if ( next.x==O.x && next.y==O.y )
							ok=0;
						D.push(next);
					}
			}
			D.pop();
		}

		// modify the right and left limits of the bsearch

		if ( !ok ) // found path
		{
			if ( answer<m ) 
			{
				answer=m;
			//	debug();
			}
			l = m+1;
		}
		else
		{
			r = m-1;
		}
	}
}

void debug()
{
	long i,j;
	for (i=0; i<R; ++i)
	{
		for (j=0; j<C; ++j)
			if ( V[i][j]!= BIG_ONE )
				printf("%6ld ", B[i][j]);
			else 
				printf("  MARE ");
		printf("\n");
	}
	printf("\n\n");	

}

void write_data()
{
	freopen(FOUT, "w", stdout);
	printf("%ld\n", answer);
	fclose(stdout);
}

int main()
{
	read_data();
	solve();
	write_data();
	return 0;
}