Cod sursa(job #2716591)

Utilizator rapidu36Victor Manz rapidu36 Data 5 martie 2021 13:05:50
Problema Barbar Scor 90
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.26 kb
#include <fstream>
#include <queue>

using namespace std;

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

const int N = 1e3;
int dist[N+1][N+1];
bool obs[N+2][N+2],visited[N+1][N+1];
struct pos
{
    int y,x;
} start,finish;
int dy[] = {1,0,0,-1};
int dx[] = {0,1,-1,0};
int y,x,maxdist;
queue <pos> q;

void calcDistMin()
{
    while(!q.empty())
    {
        pos root = q.front();
        q.pop();
        for(int i=0; i<4; ++i)
        {
            int new_y = root.y + dy[i], new_x = root.x + dx[i];
            if(!obs[new_y][new_x] && dist[new_y][new_x]==0)
            {
                dist[new_y][new_x] = dist[root.y][root.x]+1;
                if(dist[new_x][new_x] > maxdist)
                {
                    maxdist = dist[new_y][new_x];
                }
                q.push({new_y,new_x});
            }
        }
    }
}

void clearVisited()
{
    for(int i=1; i<=y; ++i)
    {
        for(int j=1; j<=x; ++j)
            visited[i][j]=0;
    }
}

bool isPath(int distance)
{
    clearVisited();
    q = queue <pos>({start});
    visited[start.y][start.x] = 1;
    while(!q.empty())
    {
        pos root = q.front();
        q.pop();
        for(int i=0; i<4; ++i)
        {
            int new_y = root.y + dy[i], new_x = root.x + dx[i];
            if(!visited[new_y][new_x] && !obs[new_y][new_x] && dist[new_y][new_x]>=distance)
            {
                if(new_y == finish.y && new_x == finish.x)
                {
                    return true;
                }
                q.push({new_y,new_x});
                visited[new_y][new_x]=1;
            }
        }
    }
    return false;
}

int findSol()
{
    /*
    int st=1,dr = maxdist,mij;
    bool existaPath = false;
    while(st+1<dr)
    {
        mij = (st+dr)/2;
        if(isPath(mij))
        {
            st = mij;
            existaPath = true;
        }
        else
            dr=mij-1;
    }
    return existaPath ? st : -1;
    */
    int r = 0, pas = 1 << 10;
    while (pas != 0)
    {
        if (isPath(r + pas))
        {
            r += pas;
        }
        pas /= 2;
    }
    if (r == 0)
    {
        r = -1;
    }
    return r;
}

void bordare()
{
    for(int i=0; i<=y+1; ++i)
        obs[i][0] = obs[i][x+1] = 1;
    for(int i=0; i<=x+1; ++i)
        obs[0][i] = obs[y+1][i] = 1;
}

int main()
{
    cin>>y>>x;
    for(int i=0; i<y; ++i)
    {
        char l[x+1];
        cin>>l;
        for(int j=0; j<x; ++j)
        {
            switch (l[j])
            {
            case 'I':
            {
                start.y = i+1;
                start.x = j+1;
                break;
            }
            case 'O':
            {
                finish.y = i+1;
                finish.x = j+1;
                break;
            }
            case '*':
            {
                obs[i+1][j+1]=1;
                break;
            }
            case 'D':
            {
                q.push({i+1,j+1});
                dist[i+1][j+1] = 1;
                break;
            }

            }
        }
    }
    bordare();
    calcDistMin();
    int solutie = findSol();
    cout<<( (solutie==-1) ? -1 : solutie-1);
    return 0;
}