Cod sursa(job #1026844)

Utilizator TripluYOlteanu Costin TripluY Data 12 noiembrie 2013 03:38:32
Problema Barbar Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.89 kb
#include <fstream>
#include <vector>
#include <queue>
#include <cmath>
#define MAXINT 0x7FFFFFFF
using namespace std;

struct ptemnita
{
    char c;
    int distanta_dragon;
    bool vizitat;
};

struct punct
{
    int x,y;
    punct()
    {
        x = y = 0;
    }
    punct(int a,int b)
    {
        x = a;
        y = b;
    }
    bool operator ==(const punct &alt)
    {
        return (alt.x == x && alt.y == y);
    }
};

ptemnita **temnita;
punct start,destinatie;
int r,c;

inline void deviziteaza()
{
    int i,j;
    for(i=0;i<r;++i)
        for(j=0;j<c;++j)
            temnita[i][j].vizitat = false;
}

void flood(int x,int y,int distanta)
{
    if(x < 0 || y < 0 || x >= r || y >= c)
        return;
    if(temnita[x][y].distanta_dragon <= distanta || temnita[x][y].c == '*')
        return;
    temnita[x][y].distanta_dragon = distanta;
    ++distanta;
    flood(x - 1,y,distanta);
    flood(x + 1,y,distanta);
    flood(x,y - 1,distanta);
    flood(x,y + 1,distanta);
}

bool parcurge(int apropiere)
{
    deviziteaza();
    queue <punct> puncte_nevizitate;
    punct locatie_curenta;
    puncte_nevizitate.push(punct(start.x,start.y));
    do
    {
        locatie_curenta = puncte_nevizitate.front();
        puncte_nevizitate.pop();
        if(temnita[locatie_curenta.x][locatie_curenta.y].vizitat == true || temnita[locatie_curenta.x][locatie_curenta.y].distanta_dragon < apropiere || temnita[locatie_curenta.x][locatie_curenta.y].c == '*')
            continue;
        temnita[locatie_curenta.x][locatie_curenta.y].vizitat = true;
        if(locatie_curenta == destinatie)
            return true;
        if(locatie_curenta.x > 0)
            puncte_nevizitate.push(punct(locatie_curenta.x - 1,locatie_curenta.y));
        if(locatie_curenta.x < r - 1)
            puncte_nevizitate.push(punct(locatie_curenta.x + 1,locatie_curenta.y));
        if(locatie_curenta.y > 0)
            puncte_nevizitate.push(punct(locatie_curenta.x,locatie_curenta.y - 1));
        if(locatie_curenta.y < c - 1)
            puncte_nevizitate.push(punct(locatie_curenta.x,locatie_curenta.y + 1));
    }
    while(!puncte_nevizitate.empty());
    return false;
}

int main()
{
    ifstream f("barbar.in");
    f>>r>>c;
    temnita = new ptemnita*[r];
    vector <punct> dragoni;
    for(int i=0;i<r;++i)
    {
        temnita[i] = new ptemnita[c];
    }
    for(int i=0;i<r;++i)
        for(int j=0;j<c;++j)
        {
            temnita[i][j].distanta_dragon = MAXINT;
            f>>temnita[i][j].c;
            switch(temnita[i][j].c)
            {
            case 'D':
                dragoni.push_back(punct(i,j));
                break;
            case 'I':
                start.x = i;
                start.y = j;
                break;
            case 'O':
                destinatie.x = i;
                destinatie.y = j;
                break;
            }
            if(temnita[i][j].c == 'D')
                dragoni.push_back(punct(i,j));

        }
    for(vector<punct>::iterator it=dragoni.begin();it != dragoni.end();it++)
    {
        flood(it->x,it->y,0);
    }
    ofstream g("barbar.out");
    if(!parcurge(0))
        g<<-1;
    else
    {
        int dist_max = min(temnita[start.x][start.y].distanta_dragon,temnita[destinatie.x][destinatie.y].distanta_dragon);
        int dist_min = 0;
        int incercare;
        while(abs(dist_max - dist_min) > 1)
        {
            incercare = (dist_min + dist_max) / 2;
            if(parcurge(incercare))
                dist_min = incercare;
            else
                dist_max = incercare;
        }
        if(dist_max != dist_min)
        {
            if(parcurge(dist_max))
                g<<dist_max;
            else
                g<<dist_min;
        }
        else
            g<<dist_min;
    }
    g.close();
    return 0;
}