Cod sursa(job #582459)

Utilizator DaNutZ2UuUUBB Bora Dan DaNutZ2UuU Data 15 aprilie 2011 13:22:07
Problema Barbar Scor 100
Compilator cpp Status done
Runda brasov_final_round Marime 3.13 kb
#include<fstream>
#include<queue>
#define dmax 1010
using namespace std;

typedef struct pozitie
{
 int l,c;
} pozitie;

int n,m;
int a[dmax][dmax];
/*matricea cu distantele minime pana la un dragom*/
int pil,pic,pfl,pfc;
queue<pozitie> q,q2;
/*cozi care au initial pozitiile dragonilor*/
int dx[4]={-1,0,1,0},dy[4]={0,-1,0,1};
int drmax=-1;
/*drmax = solutia*/
bool b[dmax][dmax];
/*matricea caracteristica pentru marcarea casutelor vizitate in verificare*/


void citire()
{
 int i,j;
 char c;
 pozitie aux;
	
 ifstream fin("barbar.in");
 fin>>n>>m;
 for (i=1; i<=n; i++)
	 for (j=1; j<=m; j++)
		 {
		  fin>>c;
		  if (c == 'D')
			  {
			   aux.l = i; aux.c = j;
			   q.push(aux);
			   q2.push(aux);
			  } else
			  if (c == 'I')
				  {
				   pil = i; pic = j;
				  } else
				  if (c == 'O')
					  {
					   pfl = i; pfc = j;
					  } else
					  if (c == '*')
						  a[i][j] = -1;		  
		 }

 fin.close();
}


/*distantele minime de la fiecare celula pana la un dragon*/
void distante()
{
 pozitie elem,aux;
 int k;
	
 while (!q.empty())
	 {
	  elem = q.front();
	  
	  for (k=0; k<4; k++)
		  if (elem.l + dx[k] >= 1 && elem.l + dx[k] <= n && elem.c + dy[k] >= 1 && elem.c + dy[k] <= m)
			  if (a[elem.l + dx[k]][elem.c + dy[k]] > a[elem.l][elem.c] + 1 || a[elem.l + dx[k]][elem.c + dy[k]] == 0)
				  {
				   a[elem.l + dx[k]][elem.c + dy[k]] = a[elem.l][elem.c] + 1;
				   aux.l = elem.l + dx[k]; aux.c = elem.c + dy[k];
				   q.push(aux);
				  }
		
	  q.pop();
	 }
}


/*marchez cu 0 pozitiile dragonilor*/
void restituire()
{
 int i,lg;
 pozitie elem;
	
 lg = q2.size();
 for (i=0; i<lg; i++)
	 {
	  elem = q2.front();
	  a[elem.l][elem.c] = 0;
	  q2.pop();
	 }
}


/*curat coada si matricea caracteristica*/
void clear()
{
 int i,j;
	
 while (!q.empty())
	 q.pop();
 for (i=1; i<=n; i++)
	 for (j=1; j<=m; j++)
		 b[i][j] = 0;
}


/*verific daca pot merge pe un traseu cu distanta minima dimmax pana la un dragon*/
int verifica(int dimmax)
{
 pozitie aux,elem;
 int k;
	
 clear();
 
 b[pil][pic] = 1;
 aux.l = pil; aux.c = pic;
 q.push(aux);
 
 while (!q.empty())
	 {
	  elem = q.front();
	  
	  if (elem.l == pfl && elem.c == pfc)
		  return 1;
	  
	  for (k=0; k<4; k++)
		  if (elem.l + dx[k] >= 1 && elem.l + dx[k] <= n && elem.c + dy[k] >= 1 && elem.c + dy[k] <= m)
			  if (a[elem.l + dx[k]][elem.c + dy[k]] >= dimmax && b[elem.l + dx[k]][elem.c + dy[k]] == 0)
				  {
				   b[elem.l + dx[k]][elem.c + dy[k]] = 1;
				   aux.l = elem.l + dx[k]; aux.c = elem.c + dy[k];
				   q.push(aux);
				  }
		  
	  q.pop();
	 }
 
 return 0;
}


/*caut binar solutia*/
void cauta(int st, int dr)
{
 int mijl;

 mijl = (st + dr) / 2;
 if (st <= dr) 
	 {
	  if (verifica(mijl))
		  {
		   drmax = max(drmax, mijl);
		   cauta(mijl+1, dr); 
		  } else
		  cauta(st, mijl-1);
		  
	 }
}


void afisare()
{
 ofstream fout("barbar.out");
 
 fout<<drmax<<'\n';
 
 fout.close();
}


int main()
{
	
 citire();
 distante();
 restituire();
 cauta(0, min(a[pil][pic], a[pfl][pfc]));
 afisare();
	
 return 0;
}