Pagini recente » Rating Sigartau Larisa (lary_kiss007) | Monitorul de evaluare | Cod sursa (job #1109434) | Cod sursa (job #2032650) | Cod sursa (job #3295270)
#include <bits/stdc++.h>
#define NMAX 1000
#define inf 1000000000
using namespace std;
int r, c;
pair<int, int> poz_intrare, poz_iesire; //coordonatele punctului de plecare a barbarului si a iesirii din temnita
char a[NMAX][NMAX]; //matricea citita
int distanta[NMAX][NMAX]; //distanta de la fiecare celula la un dragon
int ox[4]={0, 1, 0, -1}; //vectorii de directie
int oy[4]={1, 0, -1, 0};
bool d_intrare_iesire(int val) //returneaza 1 daca se poate ajunge de la intrare la iesire trecand doar prin celule cu distante mai mari sau egale cu val si 0 daca nu se poate
{
queue<pair<int, int>> coada; //vom folosi algoritmul lui lee pentru a determina daca se poate ajunge de la intrare le un punct din matrice
array<array<bool, NMAX>, NMAX> poate_ajunge; //salvam 1 daca se poate ajunge la acea celula (trecand doar prin celule cu valori mai mari sau egale cu val) si 0 daca nu
for(int i=0; i<r; i++) for(int j=0; j<r; j++) poate_ajunge[i][j]=0; //initializam matricea poate_ajunge cu 0
poate_ajunge[poz_intrare.first][poz_intrare.second]=1;
coada.push(poz_intrare);
while(!coada.empty())
{
pair<int, int> poz=coada.front();
coada.pop();
for(int i=0; i<4; i++)
{
pair<int, int> nou={poz.first+ox[i], poz.second+oy[i]}; //vecinul lui poz
if((nou.first>=0 && nou.first<r) && (nou.second>=0 && nou.second<c) && (a[nou.first][nou.second]!='*' && a[nou.first][nou.second]!='D')) //daca pozitia vecinului este in matrice si este o pozitie libera
{
if(distanta[nou.first][nou.second]>=val && poate_ajunge[nou.first][nou.second]==0) //daca celula are o valoare mai mare sau egala cu val si nu am parcurs-o pana acum
{
poate_ajunge[nou.first][nou.second]=1; //salvam ca se poate ajunge la pozitie
coada.push(nou); //adaugam vecinul la coada
}
}
}
}
return poate_ajunge[poz_iesire.first][poz_iesire.second];
}
int cautare_binara() //cauta binar cea mai mare distanta pentru care putem gasi un drum de la intrare la iesire format numai din valori mai mari sau egale cu acea distanta
{
int st=0, dr=distanta[poz_intrare.first][poz_intrare.second], distanta_maxima=0; //capetele stanga si dreapta pentru cautarea binara si distanta maxima ceruta
while(st<=dr)
{
int mij=st+(dr-st)/2;
if(d_intrare_iesire(mij)==1) //daca se poate ajunge la iesire astfel incat toate celulele prin care se trece sa aiba distante mai mari sau egale cu mij
{
st=mij+1;
distanta_maxima=mij;
}
else //daca nu
{
dr=mij-1;
}
}
return distanta_maxima;
}
int main()
{
ifstream cin("barbar.in");
ofstream cout("barbar.out");
cin >> r >> c;
for(int i=0; i<r; i++) //initializam vectorul de distante cu infinit
for(int j=0; j<c; j++)
distanta[i][j]=inf;
queue<pair<int, int>> coada; //coada pentru algoritmul lui lee
for(int i=0; i<r; i++)
{
for(int j=0; j<c; j++)
{
cin >> a[i][j];
if(a[i][j]=='I') //daca am gasit intrarea
{
poz_intrare={i, j}; //salvam pozitia intrarii
}
if(a[i][j]=='O') //daca am gasit iesirea
{
poz_iesire={i, j}; //salvam pozitia iesirii
}
if(a[i][j]=='D') //daca am gasit un dragon
{
coada.push({i, j}); //salvam pozitia dragonului in coada
distanta[i][j]=0; //salvam distanta de la celula la dragon ca fiind 0
}
}
}
//vom folosi algoritmul lui lee pentru a afla distanta fiecarei celule de la cel mai apropiat dragon
while(!coada.empty())
{
pair<int, int> poz=coada.front();
coada.pop();
for(int i=0; i<4; i++)
{
pair<int, int> nou={poz.first+ox[i], poz.second+oy[i]}; //vecinul lui poz
if((nou.first>=0 && nou.first<r) && (nou.second>=0 && nou.second<c))
{
if(a[nou.first][nou.second]!='*' && distanta[nou.first][nou.second]==inf) //daca celula este goala nu am parcurs-o pana acum
{
distanta[nou.first][nou.second]=1+distanta[poz.first][poz.second]; //salvam distanta de la dragon pana la celula
coada.push(nou); //adaugam vecinul la coada
}
}
}
}
//vom cauta binar cea mai mare distanta pentru care putem gasi un drum de la intrare la iesire format numai din valori mai mari sau egale cu acea distanta
int distanta_maxima=cautare_binara();
if(distanta_maxima==0) //daca distanta maxima ajunge sa fie 0, inseamna ca nu este posibil sa se ajunga de la intrare la iesire, deci afisam -1
cout << -1;
else //altfel, afisam distanta maxima
cout << distanta_maxima;
return 0;
}