Cod sursa(job #2954701)

Utilizator anetAneta Anghel anet Data 15 decembrie 2022 08:38:03
Problema Barbar Scor 40
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.25 kb
#include <fstream>
#include <vector>
#include <queue>
#include <tuple>
using namespace std;

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

const int di[] = {-1, 1, 0, 0},
          dj[] = {0, 0, -1, 1},
          Inf  = 1e6,
          N    = 1007;

using PI  = pair<int, int>;
using VI  = vector<int>;
using VVI = vector<VI>;
using VB  = vector<bool>;
using VVB = vector<VB>;

VVI d;
VVB v;
VVB mat;
int n, m;
int ip, jp, is, js;
vector<PI> dragoni;

void CitesteDate();
bool ok1(int i, int j);
bool ok2(int i, int j, int D);
void DistMinFataDeDragoni();
bool PoateTrece(int X);
int CautBinDistMax();

int main()
{
    CitesteDate();
    DistMinFataDeDragoni();

    int dmax = CautBinDistMax();
    fout << dmax;

    return 0;
}

int CautBinDistMax()
{
    int st = 1, dr = N, m, dmax = -1;
    while (st <= dr)
    {
        m = st + (dr - st) / 2;
        if (PoateTrece(m))
        {
            dmax = max(dmax, m);
            st = m + 1;
        }
        else
            dr = m - 1;
    }

  //  if (d[ip][jp] < dmax)
  //      dmax = d[ip][jp];
    return dmax;
}

bool ok2(int i, int j, int D)
{
    if (i < 1 || i > n || j < 1 || j > m)
        return false;
    if (mat[i][j])
        return false;

    if (v[i][j])  // celula vizitata anterior
        return false;

    if (d[i][j] < D)   // daca se apropie de un dragon la dist ma mica decat D
        return false;
  return true;
}


#define iv (i + di[p])
#define jv (j + dj[p])

bool PoateTrece(int D)
{
    queue<PI> Q;
    v = VVB(n + 1, VB(m + 1));

    v[ip][jp] = true;
    Q.emplace(ip, jp);
    int i, j;
    while (!Q.empty())
    {
        tie(i, j) = Q.front();
        Q.pop();

        for (int p = 0; p < 4; ++p)
            if (ok2(iv, jv, D))
            {
                v[iv][jv] = true;
                if (iv == is && jv == is)
                    return true;
                Q.emplace(iv, jv);
            }
    }

    return false;
}

void DistMinFataDeDragoni()
{
    queue<PI> Q;

    d = VVI(n + 1, VI(m + 1, Inf));
    int i, j;
    for(auto &dragon: dragoni)
    {
        tie(i, j) = dragon;
        d[i][j] = 0;
        Q.push(dragon);
    }

    while (!Q.empty())
    {
        tie(i, j) = Q.front();
        Q.pop();

        for(int p = 0; p < 4; ++p)
            if (ok1(iv, jv) && d[iv][jv] > d[i][j] + 1)
            {
                d[iv][jv] = d[i][j] + 1;
                Q.emplace(iv, jv);
            }
    }
}

bool ok1(int i, int j)
{
    if (i < 1 || i > n || j < 1 || j > m)
        return false;
    if (mat[i][j]) return false;
    return true;
}

void CitesteDate()
{
    fin >> n >> m;

    mat = VVB(n + 1, VB(m + 1));

    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j)
        {
            char c;
            fin >> c;

            if (c == '*')
                mat[i][j] = true;

            if (c == 'I')
            {
                ip = i;
                jp = j;
            }

            if (c == 'O')
            {
                is = i;
                js = j;
            }

            if (c == 'D')
            {
                dragoni.emplace_back(i, j);
            }
        }
}