Cod sursa(job #2562243)

Utilizator Iulia25Hosu Iulia Iulia25 Data 29 februarie 2020 13:01:15
Problema Barbar Scor 20
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.85 kb
#include <fstream>

using namespace std;

ifstream fin ("barbar.in");
ofstream fout ("barbar.out");

const int N = 1005;

int n, m, stc, drc;
int nr, l, c, dist[N][N], L, C, LF, CF;
char a[N][N]; //matricea citita
bool viz[N][N];
int dl[] = {-1, 0, 0, 1};
int dc[] = {0, -1, 1, 0};

struct punct	{
	int l, c, nr; //linia, coloana, distanta minima fata de oricare din dragoni
} q[N * N];

void reinit()  {
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= m; ++j)
			viz[i][j] = 0;
	for (int i = 1; i <= drc; ++i)
		q[i] = {0, 0, 0};
	stc = 0, drc = 0;
}

bool bfs(int k)  { //distanta minima pe care ma pot deplasa
	reinit(); //reinitializez viz si coada
	q[1] = {L, C, 0};
	stc = drc = 1;
	viz[L][C] = true;
	while (stc <= drc)  {
		l = q[stc].l;
		c = q[stc].c;
		++stc;
		for (int i = 0; i < 4; ++i)	 {
			if (l + dl[i] == 0 || c + dc[i] == 0 || l + dl[i] > n || c + dc[i] > m); //verific daca ies din matrice
			else	{
				if (a[l + dl[i]][c + dc[i]] != '*'  //pozitia (l + dl[i], c + dc[i]) nu este perete
					&& !viz[l + dl[i]][c + dc[i]] //si nu a fost vizitata inca
					&& dist[l + dl[i]][c + dc[i]] >= k) //si este 'accesibila', adica nu are distanta fata de un dragon mai mica decat k
				{
					q[++drc] = {l + dl[i], c + dc[i], 0}; //il bag pe (l + dl[i], c + dc[i]) in coada
					viz[l + dl[i]][c + dc[i]] = true; //si il marchez ca vizitat
				}
			}
		}
	}
	if (viz[LF][CF])
		return true;
	return false;
}

int main()  {
	fin >> n >> m; //citesc dimensiunile matricii
	for (int i = 1; i <= n; ++i)  {
		for (int j = 1; j <= m; ++j)  {
			fin >> a[i][j]; //citesc matricea
			if (a[i][j] == 'D')  {
				q[++drc] = {i, j, 0}; //introduc in coada coordonatele dragonului
				                     //si distanta lui minima fata de oricare din dragoni (0)
			}
			if (a[i][j] == 'I')
				L = i, C = j; //retin coordonatele punctului de start
			if (a[i][j] == 'O')
				LF = i, CF = j; //retin coordonatele punctului de finish
		}
	}
	stc = 1;
	while (stc <= drc)  {
		l = q[stc].l;
		c = q[stc].c;
		nr = q[stc].nr;
		++stc;
		for (int i = 0; i < 4; ++i)	 { //parcurg vecinii elementului
			if (l + dl[i] == 0 || c + dc[i] == 0 || l + dl[i] > n || c + dc[i] > m); //verific daca ies din matrice
			else if (dist[l + dl[i]][c + dc[i]] == 0 && a[l + dl[i]][c + dc[i]] != 'D')  { //verific daca nu am mai trecut elementul (l + dl[i], c + dc[i])
				q[++drc] = {l + dl[i], c + dc[i], nr + 1}; //il introduc in coada
				dist[l + dl[i]][c + dc[i]] = nr + 1;
			}
		}
	}
	//acum dist[i][j] = distanta minima de la (i, j) fata de cel mai apropiat dragon de el
	int st = dist[L][C], dr = dist[LF][CF], mij, ans = -1;
	while (st <= dr)  { //caut binar valoarea minima din dist pe care ma voi deplasa
		mij = (st + dr) / 2;
		if (bfs(mij))  { //verific daca pot ajunge de la start la finish mergand numai pe valori >= cu mij
			ans = mij;
			st = mij + 1;
		} else
			dr = mij - 1;
	}
	fout << ans;
	return 0;
}