Cod sursa(job #1043163)

Utilizator vladm97Matei Vlad vladm97 Data 28 noiembrie 2013 03:00:44
Problema Barbar Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.77 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#define infinite 9999999
using namespace std;
int n,m;
int parcurs[1010][1010];
int myDistance[1010][1010];
bool foundSolution;
bool solutionCertain;
ifstream in("barbar.in");
ofstream out("barbar.out");
int cost;
int middle;
struct pos
{
    int i;
    int j;
}A,start,finish;
queue <pos> myQueue;
vector <pos> dragons;
int caseAvailable;

void surrounder()
{
    for(int i = 0; i <= m + 1; i++)
    {
        myDistance[0][i] = infinite;
        myDistance[n+1][i] = infinite;
        parcurs[0][i] = infinite;
        parcurs[n+1][i] = infinite;
    }

    for(int i = 0; i <= n; i++)
    {
        myDistance[i][0] = infinite;
        myDistance[i][m+1] = infinite;
        parcurs[i][0] = infinite;
        parcurs[i][m+1] = infinite;
    }
}

void read()
{
    char ch;
    in>>n>>m;
    surrounder();
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            myDistance[i][j] = infinite;
            in>>ch;
            if(ch == '.')
            {

            }
            else
            {
                if(ch == '*')
                {
                    parcurs[i][j] = infinite;
                }
                else
                {
                    if(ch == 'D')
                    {
                        A.i = i;
                        A.j = j;
                        dragons.push_back(A);
                        myDistance[i][j] = 0;
                        parcurs[i][j] = infinite;
                    }
                    else
                    {
                        if(ch == 'I')
                        {
                            start.i = i;
                            start.j = j;
                        }
                        else
                        {
                            finish.i = i;
                            finish.j = j;
                        }
                    }
                }
            }
        }
    }
}

void queueUp(int i, int j)
{
    if(parcurs[i-1][j] < caseAvailable)
    {
        parcurs[i-1][j] = caseAvailable;
        if((myDistance[i-1][j] > myDistance[i][j] + 1) || myDistance[i-1][j] == 0)
        {
            parcurs[i-1][j] = caseAvailable;
            A.i = i-1;
            A.j = j;
            myDistance[i-1][j] = myDistance[i][j] + 1;
            myQueue.push(A);
        }
    }
}

void queueMiddle(int i, int j)
{
    if(parcurs[i][j-1] < caseAvailable)
    {
        parcurs[i][j-1] = caseAvailable;
        if( myDistance[i][j-1] > myDistance[i][j] + 1 )
        {
            A.i = i;
            A.j = j-1;
            myQueue.push(A);
            parcurs[i][j-1] = caseAvailable;
            myDistance[i][j-1] = myDistance[i][j] + 1;
        }
    }

    if(parcurs[i][j+1] < caseAvailable )
    {
        if(myDistance[i][j+1] > myDistance[i][j] + 1)
        {
            A.i = i;
            A.j = j+1;
            myQueue.push(A);
            parcurs[i][j+1] = caseAvailable;
            myDistance[i][j+1] = myDistance[i][j] + 1;
        }
    }
}

void queueDown(int i, int j)
{
    if(parcurs[i+1][j] < caseAvailable)
    {
       if(myDistance[i+1][j] > myDistance[i][j] + 1)
        {
            parcurs[i+1][j] = caseAvailable;
            myDistance[i+1][j] = myDistance[i][j] + 1;
            A.i = i+1;
            A.j = j;
            myQueue.push(A);
        }
    }
}
void queueMyNeighbours(int i, int j)
{
    queueUp(i,j);
    queueMiddle(i,j);
    queueDown(i,j);
}

void setmyDistance()
{
    pos aux;
    while(myQueue.empty() == false)
    {
        aux = myQueue.front();
        myQueue.pop();
        queueMyNeighbours(aux.i,aux.j);
    }
}

void dragonIt()
{
    for(int i = 0; i < dragons.size(); i++)
    {
        caseAvailable++ ;
        myQueue.push(dragons[i]);
        setmyDistance();
    }
}

void df(int i, int j)
{
    parcurs[i][j] = caseAvailable;
    if(i == finish.i && j == finish.j)
    {
        foundSolution = true;
    }
    else
    {
        if(foundSolution == false)
        {
            if(parcurs[i-1][j] < caseAvailable && myDistance[i-1][j] >= middle)
            {
                df(i-1,j);
            }
            if(parcurs[i+1][j] < caseAvailable && myDistance[i+1][j] >= middle)
            {
                df(i+1,j);
            }
            if(parcurs[i][j-1] < caseAvailable && myDistance[i][j-1] >= middle )
            {
                df(i,j-1);
            }
            if(parcurs[i][j+1] < caseAvailable && myDistance[i][j+1] >= middle)
            {
                df(i, j+1);
            }
        }
    }
}

int bsc()
{
    int step,i;
    for (step = 1; step < n + m + 1; step <<= 1)
    {

    }

    for (i = 0; step; step >>= 1)
    {
        foundSolution = false;
        if(i + step < n*m+1)
        {
            foundSolution = false;
            middle = i + step;
            df(start.i,start.j);
            if(foundSolution == true)
            {
                i = i + step;
                solutionCertain = true;
            }
        }
    }
    return i;
}

void writeMatrix()
{
    for(int i = 1 ; i<=n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            if(myDistance[i][j] == infinite)
            {
                out<<"* ";
            }
            else
            out<<myDistance[i][j]<<" ";
        }
        out<<endl;
    }
}
void solve()
{
    dragonIt();
    caseAvailable++;
    middle = bsc();
}

void write()
{
    if (solutionCertain == false)
    {
        out<<-1;
    }
    else
    {
        out<<middle;
    }
}

main()
{
    read();
    solve();
    write();
}