Cod sursa(job #773417)

Utilizator danalex97Dan H Alexandru danalex97 Data 1 august 2012 17:22:57
Problema Barbar Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.96 kb
/*
#include <fstream>
#include <queue>
#include <cstring>
using namespace std;

#define Nmax 1011
#define x first
#define y second

#define cost first
#define k1 second.first
#define k2 second.second

ifstream F("barbar.in");
ofstream G("barbar.out");

typedef pair<int,int> Pair;
typedef pair<int,Pair> Grupe;

queue< Pair > Q;

int D[Nmax][Nmax];
int Marked[Nmax][Nmax];
int Viz[Nmax][Nmax];
int Max;

int Lee[Nmax][Nmax];
queue< Pair > Q2;

char chr;
int N,M;

Pair Start,End;

int Dx[]={ 0 , -1 , 1 , 0 ,  0 };
int Dy[]={ 0 ,  0 , 0 , 1 , -1 };

void Get(int i,int j)
{
	F>>chr;
	switch( chr )
	{
		case 'I':
			Start.x=i;
			Start.y=i;
			break;
		case 'O':
			End.x=i;
			End.y=i;
			break;
		case '.':
			break;
		case 'D':
			D[i][j]=-1;
			Q.push( make_pair(i,j) );
			break;
		case '*':
			D[i][j]=-1;
			break;
	}
}

inline int in(int x,int y)
{
	if ( x>0 && x<=N && y>0 && y<=M ) 
		return 1;
	return 0;
}


bool Ver()
{
	Q2.push( Start );
	while ( Q2.size() )
	{
		int i=Q2.front().x;
		int j=Q2.front().y;
		
		for (int k=1;k<5;++k)
			if ( in(i+Dx[k], j+Dy[k]) )
				if ( !Lee[ i+Dx[k] ][ j+Dy[k] ] && !D[ i+Dx[k] ][ j+Dy[k] ] )
				{
					Lee[ i+Dx[k] ][ j+Dy[k] ]=1;
					Q2.push( make_pair(i+Dx[k],j+Dy[k]) );
				}
		
		Q2.pop();
	}
	return Lee[End.x][End.y];
}

int Okay(int);

void Bs()
{
	int St,Dr,Mij;
	
	St=0;
	Dr=N*M;
	
	while ( St<=Dr )
	{
		Mij=(St+Dr)/2;
		
		if( Okay(Mij) )		
		{
			Max=max(Max,Mij);
			St=Mij+1;
		}
		else
			Dr=Mij-1;
	}
}

int main()
{
	F>>N>>M;
	
	for (int i=1;i<=N;++i)
		for (int j=1;j<=N;++j)
			Get(i,j);
	
	if ( ! Ver() )
	{
		G<<"-1\n";
		return 0;
	}		
	
	while ( Q.size() )
	{
		int i=Q.front().x;
		int j=Q.front().y;
		
		for (int k=1;k<5;++k)
			if ( in(i+Dx[k], j+Dy[k]) )
				if ( !D[ i+Dx[k] ][ j+Dy[k] ] )
				{
					D[ i+Dx[k] ][ j+Dy[k] ]=(D[i][j]==-1 ? 0 : D[i][j])+1;
					Q.push( make_pair(i+Dx[k],j+Dy[k]) );
				}
		
		Q.pop();
	}
	
	Bs();
	
	G<<Max<<'\n';
}

int Okay( int Val )
{
	int i,j,k;
	for( i=1;i<=N;i++)
		for( j=1;j<=M;j++)
			Viz[i][j]=0;
	while( !Q.empty() ) Q.pop();
	
	Pair aux,poz;
	Q.push( Start );
	
	Viz[Start.x][Start.y]=1;
	
	if ( D[Start.x][Start.y] < Val)
		return 0;
	
	while( !Q.empty() )
	{
		aux = Q.front();
		Q.pop();
		
		if( aux.x==End.x && aux.y==End.y ) return 1;
		
		for( k=1;k<5;k++ )
		{
			poz.x=aux.x+Dx[k];
			poz.y=aux.y+Dy[k];
			
			if(!Viz[poz.x][poz.y] && D[poz.x][poz.y]!=-1 && D[poz.x][poz.y]>=Val && in(poz.x,poz.y))
			{
				Viz[poz.x][poz.y]=1;
				Q.push( poz );
			}
		}
	}
	return 0;
}
*/
#include<fstream>
#include<queue>
#include<cmath>

using namespace std;

int n,m,sol=-1;
int mat[1010][1010],dist[1010][1010];

struct Pozitie{int x,y;};
Pozitie start,final;

queue <Pozitie> Q;
bool viz[1010][1010];

int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};

inline void Citire()
{
	int i,j;
	Pozitie aux;
	char s[1010];
	ifstream fin("barbar.in");
	fin>>n>>m;
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++)
			dist[i][j]=2000000000;
	for(i=0;i<=n+1;i++)
		mat[i][0]=mat[i][m+1]=-1;
	for(j=0;j<=m+1;j++)
		mat[0][j]=mat[n+1][j]=-1;
	for(i=1;i<=n;i++)
	{
		fin>>(s+1);
		for(j=1;j<=m;j++)
		{
			if(s[j]=='.')
				continue;
			if(s[j]=='*')
			{
				mat[i][j]=-1;
				continue;
			}
			if(s[j]=='D')
			{
				aux.x=i;
				aux.y=j;
				Q.push(aux);
				dist[i][j]=0;
				continue;
			}
			if(s[j]=='I')
			{
				start.x=i;
				start.y=j;
				continue;
			}
			if(s[j]=='O')
			{
				final.x=i;
				final.y=j;
				continue;
			}
		}
	}
	fin.close();
}

inline void Calculare_Distante_Dragoni()
{
	int k;
	Pozitie aux,poz;
	while(!Q.empty())
	{
		aux=Q.front();
		Q.pop();
		for(k=0;k<4;k++)
		{
			poz.x=aux.x+dx[k];
			poz.y=aux.y+dy[k];
			if(mat[poz.x][poz.y]==0 && dist[poz.x][poz.y]>dist[aux.x][aux.y]+1)
			{
				dist[poz.x][poz.y]=dist[aux.x][aux.y]+1;
				Q.push(poz);
			}
		}
	}
}

inline bool Posibil(int D)
{
	int i,j,k;
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++)
			viz[i][j]=false;
	while(!Q.empty())
		Q.pop();
	Pozitie aux,poz;
	Q.push(start);
	viz[start.x][start.y]=true;
	if(dist[start.x][start.y]<D)
		return false;
	while(!Q.empty())
	{
		aux=Q.front();
		Q.pop();
		if(aux.x==final.x && aux.y==final.y)
			return true;
		for(k=0;k<4;k++)
		{
			poz.x=aux.x+dx[k];
			poz.y=aux.y+dy[k];
			if(!viz[poz.x][poz.y] && mat[poz.x][poz.y]==0 && dist[poz.x][poz.y]>=D)
			{
				viz[poz.x][poz.y]=true;
				Q.push(poz);
			}
		}
	}
	return false;
}

inline void Cautare_Binara()
{
	int st,dr,mij;
	st=0;
	dr=n*m;
	while(st<=dr)
	{
		mij=(st+dr)/2;
		if(Posibil(mij)==true)
		{
			sol=max(sol,mij);
			st=mij+1;
		}
		else
			dr=mij-1;
	}
}

inline void Afisare()
{
	ofstream fout("barbar.out");
	fout<<sol<<"\n";
	fout.close();
}

int main()
{
	Citire();
	Calculare_Distante_Dragoni();
	Cautare_Binara();
	Afisare();
}