Pagini recente » Cod sursa (job #2267297) | Cod sursa (job #792855) | Cod sursa (job #1116595) | Cod sursa (job #425106) | Cod sursa (job #3295272)
#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]!='*') //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=-1; //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[poz.first][poz.second]+1<distanta[nou.first][nou.second]) //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
cout << cautare_binara(); //afisam distanta maxima
return 0;
}