Pagini recente » Cod sursa (job #1907052) | Cod sursa (job #889013) | Cod sursa (job #857310) | Cod sursa (job #170683) | Cod sursa (job #2208462)
#include <fstream>
using namespace std;
ifstream fin("barbar.in");
ofstream fout("barbar.out");
const int NMAX = 1005;
struct coord {
int x, y;
};
// date de intrare
int A[NMAX][NMAX], n, m;
int xS, yS, xF, yF; // coordonate plecare si sosire
int ans; // rezultat
// dragoni
int D[NMAX][NMAX]; // matrice dragoni: D[i][j] = distanta pana la cel mai apropiat dragon
coord Qd[NMAX * NMAX]; // coada dragoni
int headQd, dimQd;
// vectori de deplasare
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, -1, 0, 1};
void citire() {
fin >> n >> m;
for (int i = 1; i <= n; ++ i) {
char str[NMAX];
fin >> str;
for (int j = 1; j <= m; ++ j)
switch (str[j - 1]) {
case '.':
// camera libera => se poate intra
A[i][j] = 0;
D[i][j] = 0;
break;
case '*':
// perete => nu se poate intra
A[i][j] = -1;
D[i][j] = -1;
break;
case 'D':
// dragon
A[i][j] = 0;
D[i][j] = 1;
++ dimQd;
Qd[dimQd].x = i;
Qd[dimQd].y = j;
break;
case 'I':
// loc de plecare
A[i][j] = 1;
D[i][j] = 0;
xS = i;
yS = j;
break;
case 'O':
// loc de sosire
A[i][j] = 0;
D[i][j] = 0;
xF = i;
yF = j;
break;
}
}
}
void bordare(int A[NMAX][NMAX], int n, int m) {
// bordare matrice
for (int i = 0; i <= n + 1; ++ i)
A[i][0] = A[i][m + 1] = -1;
for (int j = 0; j <= m + 1; ++ j)
A[0][j] = A[n + 1][j] = -1;
}
void detDistDragoni() {
// determinare distanta pana la cel mai apropiat dragon (pentru fiecare camera libera)
// Lee pentru determinare distante
headQd = 1; // se garanteaza ca exista cel putin un dragon
while (headQd <= dimQd) {
int l = Qd[headQd].x;
int c = Qd[headQd].y;
++ headQd;
for (int i = 0; i < 4; ++ i) {
// determinare vecini
int ln = l + dx[i];
int cn = c + dy[i];
if (!D[ln][cn] || D[ln][cn] > D[l][c] + 1) {
// s-a gasit cel mai apropiat dragon sau s-a gasit o distanta mai mica
D[ln][cn] = D[l][c] + 1;
++ dimQd;
Qd[dimQd].x = ln;
Qd[dimQd].y = cn;
}
}
}
// actualizare distante
for (int i = 1; i <= n; ++ i)
for (int j = 1; j <= m; ++ j)
if (D[i][j] > 0)
-- D[i][j];
}
void copiereMatrici(int dest[NMAX][NMAX], int src[NMAX][NMAX]) {
// dest = src
for (int i = 0; i <= n + 1; ++ i)
for (int j = 0; j <= m + 1; ++ j)
dest[i][j] = src[i][j];
}
int B[NMAX][NMAX]; // matrice auxiliara pentru a nu pierde datele din A
coord Q[NMAX * NMAX]; // coada pentru Lee
bool Lee(int dist) {
int head = 1, dim = 0;
if (D[xS][yS] < dist) {
// camera de plecare este prea aproape de un dragon
return 0;
}
copiereMatrici(B, A);
++ dim;
Q[dim].x = xS;
Q[dim].y = yS;
while (head <= dim) {
int l = Q[head].x;
int c = Q[head].y;
++ head;
for (int i = 0; i < 4; ++ i) {
// determinare vecini
int ln = l + dx[i];
int cn = c + dy[i];
if (!B[ln][cn] && D[ln][cn] >= dist) {
// se poate accesa camera curenta
// nu ne intereseaza cea mai mica distanta, ci doar sa ajugem la destinatie
// din aceasta cauza, nu actualizam cand gasim o distanta mai buna
B[ln][cn] = B[l][c] + 1;
++ dim;
Q[dim].x = ln;
Q[dim].y = cn;
}
}
}
return B[xF][yF];
}
inline int max(const int& a, const int& b) {
return a > b ? a : b;
}
void cautareBinara() {
// cautare binara
ans = -1;
int lo = 0, hi = max(n, m);
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
int res = Lee(mid);
if (res) {
// s-a putut ajunge cu distanta dist
// incercam sa imbunatatim
lo = mid + 1;
ans = max(ans, mid);
}
else
hi = mid - 1;
}
}
int main() {
citire();
fin.close();
bordare(A, n, m);
bordare(D, n, m);
detDistDragoni();
cautareBinara();
fout << ans << "\n";
fout.close();
return 0;
}