Cod sursa(job #1703331)

Utilizator grimmerFlorescu Luca grimmer Data 16 mai 2016 20:09:53
Problema Barbar Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.84 kb
#include <fstream>
#include <string.h>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;

const int NMAX = 1000000;
int mat[1005][1005], n, m, viz[1002][1002];
char s[1002];
int dx[] = {-1, 0, 0, 1};
int dy[] = {0, 1, -1, 0};

struct point{
    int x, y;
};
point start, fin;
vector<point> drag;

void wipe(){
    int i, j;

    for(i = 1; i <= n; ++i){
        for(j = 1; j <= m; ++j){
            viz[i][j] = 0;
        }
    }
}

bool path(int val){
    queue<point> q;
    int k;
    bool ok1 = 0, ok2 = 0;
    point curr, next;

    q.push({start.x, start.y});
    wipe();
    viz[start.x][start.y] = 1;

    if(mat[start.x][start.y] >= val + 1){

        if(mat[start.x][start.y] == val + 1) ok1 = 1;

        while(!q.empty()){
            curr = q.front();
            q.pop();

            for(k = 0; k < 4; ++k){
                next.x = curr.x + dx[k];
                next.y = curr.y + dy[k];

                if(mat[next.x][next.y] > val + 1 && viz[next.x][next.y] == 0){
                    q.push(next);
                    viz[next.x][next.y] = 1;
                }
                else if(mat[next.x][next.y] == val + 1 && viz[next.x][next.y] == 0){
                    q.push(next);
                    ok1 = 1;
                    viz[next.x][next.y] = 1;
                }

                if(next.x == fin.x && next.y == fin.y) ok2 = 1;

            }

        }

        if(ok1 == 1 && ok2 == 1){
            return 1;
        }
        else{
            return 0;
        }

    }

    return 0;
}

int bin_search(){
    int med, lf = 0, rg = NMAX, rez = -1;

    while(lf <= rg){
        med = (lf + rg) / 2;

        if(path(med)){
            lf = med + 1;
            rez = med;
        }
        else{
            rg = med - 1;
        }

    }

    return rez;
}

void bordare(){
    int i;

    for(i = 0; i <= m + 1; ++i){
        mat[0][i] = -1;
        mat[n+1][i] = -1;
    }
    for(i = 0; i <= n + 1; ++i){
        mat[i][0] = -1;
        mat[i][m+1] = -1;
    }

}

void lee_drag(){
    queue<point> q;
    int i, k;
    point curr, next;

    for(i = 0; i < (int)drag.size(); ++i) q.push(drag[i]);
    while(!q.empty()){
        curr = q.front();
        q.pop();

        for(k = 0; k < 4; ++k){
            next.x = curr.x + dx[k];
            next.y = curr.y + dy[k];

            if(mat[next.x][next.y] >= 0){

                if(mat[curr.x][curr.y] > 1 && mat[next.x][next.y] == 0){
                    mat[next.x][next.y] = mat[curr.x][curr.y] + 1;
                    q.push(next);
                }
                else if(mat[curr.x][curr.y] > 1 && mat[next.x][next.y] != 0){
                     if(mat[curr.x][curr.y] + 1 < mat[next.x][next.y]) mat[next.x][next.y] = mat[curr.x][curr.y] + 1, q.push(next);
                }
                else{
                    mat[next.x][next.y] = 2;
                    q.push(next);
                }

            }

        }

    }
}

int main()
{
    int i, j, len, sol;
    freopen("barbar.in", "r", stdin);
    freopen("barbar.out", "w", stdout);

    scanf("%d%d\n", &n, &m);

    for(i = 1; i <= m; ++i){
        gets(s);
        len = strlen(s);

        for(j = 0; j < len; ++j){

            if(s[j] == '.') mat[i][j+1] = 0;
            if(s[j] == '*') mat[i][j+1] = -1;
            if(s[j] == 'I') start = {i, j+1};
            if(s[j] == 'O') fin = {i, j+1};

            if(s[j] == 'D'){
                mat[i][j+1] = 1;
                drag.push_back({i, j+1});
            }

        }

    }

    bordare();
    lee_drag();

    if(start.x == fin.x && start.y == fin.y){
        printf("%d", mat[start.x][start.y]);
    }
    else{
        sol = bin_search();
        printf("%d", sol);
    }
    return 0;
}