Cod sursa(job #406200)

Utilizator Bit_MasterAlexandru-Iancu Caragicu Bit_Master Data 1 martie 2010 12:20:38
Problema Barbar Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.31 kb
#include <cstdio>

const int N = 1001, M = 1001;

struct pct
{
	int i,j;
};

int v[N][M],n,m;
int i1,j1,i2,j2;

int dragon[N*M],nr_dragoni;

pct coada[N*M];
int p = 1, q = 0;

bool vizitat[N][M];
int dist_prim_elem;

char s[M];

void citire()
{
	scanf("%d%d\n",&n,&m);
	//gets(s);
	for (int i = 1; i <= n; ++i)
	{
		gets(s);
		for (int j = 1; j <= m; ++j)
		{
			if (s[j-1] == '.')
				v[i][j] = 0;
			if (s[j-1] == '*')
				v[i][j] = -1;
			if (s[j-1] == 'D')
			{
				v[i][j] = -1;
				coada[++q].i = i;
				coada[q].j = j;
				vizitat[i][j] = true;
			}
			if (s[j-1] == 'I')
			{
				v[i][j] = 0;
				i1 = i;
				j1 = j;
			}
			if (s[j-1] == 'O')
			{
				v[i][j] = 0;
				i2 = i;
				j2 = j;
			}
		}
	}
}

void adaugare_vecin(int i, int j)
{
	if ((i < 1)||(n < i)||(j < 1)||(m < j))
		return;
	if (v[i][j] != 0)
		return;
	if (vizitat[i][j])
		return;
	coada[++q].i = i;
	coada[q].j = j;
	v[i][j] = dist_prim_elem + 1;
	vizitat[i][j] = true;
}


void resetare_vizitat()
{
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= m; ++j)
			vizitat[i][j] = false;
}

void calculare_distante_dragoni()
{
	resetare_vizitat();
	while (p <= q)
	{
		dist_prim_elem = v[coada[p].i][coada[p].j];
		adaugare_vecin(coada[p].i-1,coada[p].j);
		adaugare_vecin(coada[p].i+1,coada[p].j);
		adaugare_vecin(coada[p].i,coada[p].j-1);
		adaugare_vecin(coada[p].i,coada[p].j+1);
		++p;
	}
}


//Exista drum de la i,j la iesire (i2,j2)?
bool exista_drum(int i, int j, int limita_liber) //Toate campurile cu valoare mai mica decat limita_liber sunt considerate ziduri.
{
	if ((i < 1)||(n < i)||(j < 1)||(m < j))
		return false;
	if (v[i][j] < limita_liber)
		return false;
	if (vizitat[i][j])
		return false;
	vizitat[i][j] = true;
	if ((i == i2)&&(j == j2))
		return true;
	if (exista_drum(i-1,j,limita_liber))
		return true;
	if (exista_drum(i+1,j,limita_liber))
		return true;
	if (exista_drum(i,j-1,limita_liber))
		return true;
	if (exista_drum(i,j+1,limita_liber))
		return true;
	return false;
}

void cautare_binara_raspuns()
{
	int rasp = 0;
	int pas = 1<<10;
	while (pas > 0)
	{
		resetare_vizitat();
		if (exista_drum(i1,j1,rasp + pas))
			rasp += pas;
		pas >>= 1;
	}
	printf("%d",(rasp ? rasp : -1));
}


int main()
{
	freopen("barbar.in","r",stdin);
	freopen("barbar.out","w",stdout);
	citire();
	calculare_distante_dragoni();
	cautare_binara_raspuns();
	return 0;
}