Cod sursa(job #2812896)

Utilizator db_123Balaban David db_123 Data 5 decembrie 2021 13:40:30
Problema Barbar Scor 90
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.99 kb
#include <fstream>
#include <queue>
#include <bitset>
///https://www.infoarena.ro/job_detail/2812738
using namespace std;

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

const int DIM = 1005;

int n, m;
int          dist[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 minDistanceDragon) {
    return (isInside(a) && !isWall(a) && !isVisited(a) && dist[a.x][a.y] >= minDistanceDragon);
}

/// calculate distance matrix
/// based on start cell from queue
void Lee_DragonDanger() {
    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);
            }
        }
    }
}

/// returns
///     true if there is a path having each point dist > minDist
///     false there is no path
bool Lee_PrisonerEscape(int minDragonDistance) {
    const int dx[] = {-1, 0, 1,  0};
    const int dy[] = { 0, 1, 0, -1};

    /// check distance from the starting point !!!
    if(dist[start.x][start.y] < minDragonDistance) {
        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();

        /// we got a solution !!!!!
        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, minDragonDistance)) {
                visited[neighbor.x][neighbor.y] = 1;
                q.push(neighbor);
            }
        }
    }

    return false;
}

/// input
/// . celula libera
/// * perete
/// D dragon
/// I punctul de plecare al lui Paftenie
/// O iesirea din temnita
int main() {

    /// reading input
    string s;
    cin >> n >> m;
    for(int i = 1; i <= n; i++) {
        cin >> s;
        s = " " + s;
        for(int j = 1; j <= m; j++) {
            if(s[j] == 'I') {
                start = {i, j};
            }
            else if(s[j] == 'O') {
                finish = {i, j};
            }
            else if(s[j] == 'D') {
                dragon[i][j]  =1;
                visited[i][j] =1;
                q.push({i, j});
            }
        }
    }

    /// fill matrix of dragon danger
    Lee_DragonDanger();

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


    /// binary search a path having a  min distance as big as possible
    int st = 1, dr = n * m, sol = -1;
    while(st <= dr){
        int mij = (st + dr) / 2;
        if(Lee_PrisonerEscape(mij)) {
            sol = mij; st = mij + 1;
        }
        else {
            dr = mij - 1;
        }
    }

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