Cod sursa(job #2812731)

Utilizator db_123Balaban David db_123 Data 4 decembrie 2021 22:49:35
Problema Barbar Scor 90
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.64 kb
#include <fstream>
#include <queue>
#include <bitset>

using namespace std;

ifstream cin("barbar.in");
ofstream cout("barbar.out");

const int DIM = 1005;

int n, m;
int     dist[DIM][DIM];
//bool visited[DIM][DIM];
//char      ma[DIM][DIM];

bitset<1>    wall[DIM][DIM];
bitset<1> visited[DIM][DIM];
bitset<1>  dragon[DIM][DIM];


struct Cell {
    int x,y;
};

queue<Cell> q;

Cell start, finish;

bool isEqual( Cell a, Cell b)
{
    return a.x == b.x and a.y == b.y;
}
bool isInside(Cell a)
{
    return ( a.x >= 1 && a.x <= n && a.y >= 1 && a.y <= m );
}
bool isWall(Cell a)
{
    return ( wall[a.x][a.y] == 1) ;
}
bool isDragon(Cell a)
{
    return ( dragon[a.x][a.y] == 1) ;
}
bool isVisited(Cell a)
{
    return ( visited[a.x][a.y] == 1) ;
}
/// cell valid = inside & not wall & not visited
bool isValid(Cell a) {
    return ( isInside(a) && !isWall(a) && !isVisited(a));
}
bool isValidAndSafer(Cell a, int D) {
    return (isInside(a) && !isWall(a) && !isVisited(a) && !isDragon(a) && dist[a.x][a.y] >= D);
}
/// calculate distance matrix
/// based on start cell from queue
void Lee_Extins() {
    const int dx[] = {-1, 0, 1,  0};
    const int dy[] = { 0, 1, 0, -1};

    while(!q.empty()) {
        Cell a = q.front();
        q.pop();
        for(int dir = 0; dir < 4; dir++) {
            Cell neighbor = {a.x + dx[dir], a.y + dy[dir]};
            if(isValid(neighbor)) {
                dist[neighbor.x][neighbor.y] = dist[a.x][a.y] + 1;
                visited[neighbor.x][neighbor.y] =  1;
                q.push(neighbor);
            }
        }
    }
}

bool Ok(int D) {
    const int dx[] = {-1, 0, 1,  0};
    const int dy[] = { 0, 1, 0, -1};

    if(dist[start.x][start.y] < D) {
        return false;
    }

    while(!q.empty()) {
        q.pop();
    }

    q.push(start);

    ///reset visited
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            visited[i][j] = 0;
        }
    }

    /// prepare Lee
    visited[start.x][start.y] = 1;

    while(!q.empty()) {
        Cell a = q.front();
        q.pop();
        if( isEqual(a,finish)) {
            return true;
        }
        for(int dir = 0; dir < 4; dir++) {
            Cell neighbor = {a.x + dx[dir], a.y + dy[dir]};
            if(isValidAndSafer(neighbor, D)) {
                visited[neighbor.x][neighbor.y] = 1;/// viz !
                q.push(neighbor);
            }
        }
    }

    return false;
}
/// input
/// . celula libera
/// * perete
/// D dragon
/// I punctul de plecare al lui Paftenie
/// O iesirea din temnita
int main() {
    string s;
    cin >> n >> m;
    for(int i = 1; i <= n; i++) {
        cin >> s;//(a[i] + 1);
        s = " " + s;
        for(int j = 1; j <= m; j++) {
            //dist[i][j] = -1;
            if(s[j] == 'I') {
                start = {i, j};
            }
            else if(s[j] == 'O') {
                finish = {i, j};
            }
            else if(s[j] == 'D') {
                //dist[i][j] = 0;
                dragon[i][j]=1;
                q.push({i, j});
            }
        }
    }

    Lee_Extins();

//    for(int i = 1 ;i <=n;i++)
//    {
//        for(int j = 1 ;j <=m;j++)
//        {
//            cout << dist[i][j]<< " ";
//        }
//        cout << "\n";
//    }


    /// binary search
    int st = 1, dr = n * m, sol = -1;
    while(st <= dr){
        int mij = (st + dr) / 2;
        if(Ok(mij)) {
            sol = mij; st = mij + 1;
        }
        else {
            dr = mij - 1;
        }
    }

    cout << sol << "\n";
    return 0;
}