Cod sursa(job #2671980)

Utilizator antonioganea3Antonio Ganea antonioganea3 Data 12 noiembrie 2020 21:42:19
Problema Barbar Scor 80
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 5.7 kb
#include <iostream>
#include <fstream>
#include <queue>
using namespace std;

int R, C;

#define max_n 1002

int M[max_n][max_n];

struct Location{
    int x;
    int y;
};

queue<Location> q;

Location start, finish;

int biggestDistVal;

void BFS( ){

    Location current;
    while(!q.empty()){
        current = q.front();

        // right
        if ( current.x+1 < C ){
            if ( M[current.x+1][current.y] == -1 ) {
                M[current.x+1][current.y] = M[current.x][current.y] + 1;
                if ( biggestDistVal < M[current.x+1][current.y] ) { biggestDistVal = M[current.x+1][current.y]; }
                q.push({current.x+1, current.y});
            }
        }

        // left
        if ( current.x-1 >= 0 ){
            if ( M[current.x-1][current.y] == -1 ) {
                M[current.x-1][current.y] = M[current.x][current.y] + 1;
                if ( biggestDistVal < M[current.x-1][current.y] ) { biggestDistVal = M[current.x-1][current.y]; }
                q.push({current.x-1, current.y});
            }
        }

        // down
        if ( current.y+1 < R ){
            if ( M[current.x][current.y+1] == -1 ) {
                M[current.x][current.y+1] = M[current.x][current.y] + 1;
                if ( biggestDistVal < M[current.x][current.y+1] ) { biggestDistVal = M[current.x][current.y+1]; }
                q.push({current.x, current.y+1});
            }
        }

        // up
        if ( current.y-1 >= 0 ){
            if ( M[current.x][current.y-1] == -1 ) {
                M[current.x][current.y-1] = M[current.x][current.y] + 1;
                if ( biggestDistVal < M[current.x][current.y-1] ) { biggestDistVal = M[current.x][current.y-1]; }
                q.push({current.x, current.y-1});
            }
        }

        q.pop();
    }
}

// up down right left
int dx[4] = {  0, 0, 1, -1 };
int dy[4] = { -1, 1, 0,  0 };

int visited[max_n][max_n];
int currentlyVisited = 1;

struct QueueElem{
    Location l;
    int dist;
};

bool look( int minimal ){
    queue<QueueElem> qu;
    QueueElem c;
    qu.push({start.x, start.y, M[start.x][start.y]});

    Location next;

    while(!qu.empty()){
        c = qu.front();
        visited[c.l.x][c.l.y] = currentlyVisited;

        for ( int i = 0; i < 4; i++ ){

            next.x = c.l.x + dx[i];
            next.y = c.l.y + dy[i];


            if ( next.x >= 0 && next.x < C && next.y >= 0 && next.y < R ){
                //cout << "next " << next.x << ' ' << next.y << endl;
                //if ( M[next.x][next.y] != -2 ) {
                    if ( visited[next.x][next.y] < currentlyVisited && M[next.x][next.y] >= minimal ){
                        //cout << "current " << c.l.x << ' ' << c.l.y << ' ' << next.x << ' ' << next.y << endl;
                        if ( next.x == finish.x && next.y == finish.y ){
                            //cout << "Found the finish";
                            currentlyVisited++;
                            return true;
                        }
                        qu.push({next, min(M[next.x][next.y], c.dist)});
                        visited[next.x][next.y] = currentlyVisited;
                    }
               // }
            }
        }

        qu.pop();
    }

    currentlyVisited++;
    return false;
}

/*
10 10
..........
.I....D...
..........
..D...D...
.*........
D*........
*...D.....
..****....
...O......
..........

. celula libera
* perete
D dragon
I punctul de plecare al lui Paftenie
O iesirea din temnita
*/

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

    fin >> R >> C;

    char temp;

    Location dragon;
    for ( int y = 0; y < R; y++ ){
        for ( int x = 0; x < C; x++ ){
            fin >> temp;
            switch(temp){
            case 'O':
                finish.x = x;
                finish.y = y;
                M[x][y] = -1;
                break;
            case 'I':
                start.x = x;
                start.y = y;
                M[x][y] = -1;
                break;
            case '.':
                M[x][y] = -1;
                break;
            case 'D':{
                M[x][y] = 0;
                dragon.x = x;
                dragon.y = y;
                q.push(dragon);

                break;
            }
            case '*':
                M[x][y] = -2;
                break;
            }
        }
    }

    BFS();

    /*
    for ( int y = 0; y < R; y++ ){
        for ( int x = 0; x < C; x++ ){
            cout << M[x][y] << ' ';
        }
        cout << endl;
    }*/

    // in cazul in care I = O
    if ( finish.x == start.x && finish.y == start.y ){
        fout << M[start.x][start.y];

        return 0;
    }


    int r = -1;

    /*
    for ( int i = 0; i < biggestDistVal; i++ ){
        if ( look( i ) ) {
            r = i;
        } else {
            break;
        }
    }*/

    int low = 0;
    int high = biggestDistVal;
    int mid = (low+high)/2;

    while ( high != low && low != mid ){
        if ( look(mid) ){ // can get higher
            r = mid;
            low = mid;
            mid = (low+high)/2;
        } else { // can get lower
            high = mid;
            mid = (low+high)/2;
        }

        //cout << low << ' ' << mid << ' ' << high << endl;
    }

    for ( int i = 0; i < 3; i++ ){
        if ( look(mid-2+i) ){
            if ( r < mid-2+i )
                r = mid-2+i;
        } else {
            break;
        }
    }



    //cout << finish.x << ' ' << finish.y;

    fout << r;

    fout.close();
    fin.close();

    return 0;
}