Cod sursa(job #2696325)

Utilizator miramaria27Stroie Mira miramaria27 Data 15 ianuarie 2021 18:29:23
Problema Barbar Scor 90
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.58 kb
#include <iostream>
#include <queue>
#include <string>
#include <algorithm>
#include <fstream>
using namespace std;

ifstream fin("barbar.in");
ofstream fout("barbar.out");

int dx[] = {  -1,  0, 0,  1 };
int dy[] = {  0,  -1, 1,  0,  };
int matrix[1002][1002], viz[1002][1002];

int n,m,k;

struct cell
{
    int x,y;
    cell(int x = 0, int y = 0):x(x),y(y) {}
};
cell start,finish;

queue<cell> c1;

int in(int x, int y)
{
    if(x >= 1 && x <= n && y >=1 && y <= m)
        return 1;
    return 0;
}
void kindalee()
{
    while(!c1.empty())
    {

        cell parent =  c1.front();
        for(int i = 0; i < 4; i++)
        {
            int x = parent.x + dx[i];
            int y = parent.y + dy[i];

            ///verificam sa nu fie perete
            if(in(x,y) == 1 && matrix[x][y] == -1)
            {

                matrix[x][y] = matrix[parent.x][parent.y] + 1;
                c1.push(cell(x,y));
            }
        }
        c1.pop();

    }
}
bool bfs(int distance)
{

    queue<cell> c2;
    c2.push(start);
    ///nu uita sa resetezi vizitarile!!!
    for(int i = 1; i <=n; i++)
        for(int j = 1; j <=m; j++)
             viz[i][j] = 0;

    viz[start.x][start.y] = 1;
    while(!c2.empty())
    {

        cell parent =  c2.front();
        ///am ajuns la finish => exista drum de distanta minim distance
        if(parent.x == finish.x && parent.y == finish.y)
            return true;

        for(int i = 0; i < 4; i++)
        {
            int x = parent.x + dx[i];
            int y = parent.y + dy[i];

            ///ca sa avem drum de distanta minim distance
            /// matrix[x][y] >= distance si sa nu fie deja vizitat
            if(in(x,y) == 1 && matrix[x][y] >= distance && !viz[x][y])
            {

                viz[x][y] = 1;
                c2.push(cell(x,y));
            }
        }
        c2.pop();

    }
    return false;

}
int maxdistance = -1;
void cautarebinara(int l, int r)
{

    if(l <=r)
    {

        int m = l + (r - l)/2;
        /// exista distanta minim m => incercam sa gasim una si mai mare => mergem in jumatatea din dreapta a
        /// plajelor de valori
        if(bfs(m))
        {
            maxdistance = m;
            cautarebinara(m+1,r);
            ///ne salvam distanta
        }
        ///altfel, mergem in jumatatea inferioara si cautam
        else
            cautarebinara(l,m-1);

    }
}
int main()
{


    ///citim datele
    fin>>n>>m;
    for(int i= 1; i<=n; i++)
    {

        for(int j = 1; j <= m; j ++)
        {
            char c;
            fin>>c;
            if(c == 'D')
            {

                //adaugam dragonii in coada
                c1.push(cell(i,j));
                matrix[i][j] = 0;
            }
            else if(c == '*')
            {
                matrix[i][j] = -2;
            }
            else
            {
                //daca avem I sau O sau .
                if (c == 'I')
                    start = cell(i,j);
                if (c == 'O')
                    finish = cell(i,j);

                matrix[i][j] = -1;
            }


        }
    }


    kindalee();
   /* for(int i = 1 ; i <= n; i ++)
    {
        for(int j = 1; j <=m; j++)
        {
            cout<<" "<<matrix[i][j]<<" ";
        }
        cout<<"\n";
    }*/
    ///facem o cautare binara
    /// distanta minima = 0
    /// distanta maxima = n*m
    cautarebinara(0,n*m);
    if(maxdistance)
      fout<<maxdistance;
    else
        fout<<-1;
    return 0;
}