Cod sursa(job #1615159)

Utilizator BrandonChris Luntraru Brandon Data 26 februarie 2016 14:06:42
Problema Barbar Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.31 kb
#include <fstream>
#include <queue>
#include <cstring>

#define INF 0x3f3f3f3f

using namespace std;

ifstream cin("barbar.in");
ofstream cout("barbar.out");

class Coord {
public:
    int x, y;
    inline bool operator == (Coord other) {
        return x == other.x and y == other.y;
    }
};

class PrioQ {
public:
    int cost/*, dist*/;
    Coord pos;
};

class cmp {
public:
    inline bool operator ()(PrioQ a, PrioQ b) {
        return a.cost < b.cost;
    }
};

queue <Coord> q;

Coord paft, drag[1000005], ext;
int n, m, cost[1005][1005], drag_nr = 1, min_cost = INF;
int dir[4][2] = {{0, -1}, {-1, 0}, {0, 1}, {1, 0}};
bool used[1005][1005];

void bord_matrix() {
    for(int i = 0; i <= n + 1; ++i) {
        cost[i][0] = -1;
        cost[i][m + 1] = -1;
    }

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

void fill_dragon() {
    for(int i = 1; i < drag_nr; ++i) {
        cost[drag[i].x][drag[i].y] = 1;
        used[drag[i].x][drag[i].y] = true;
        q.push(drag[i]);
    }

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

        for(int i = 0; i < 4; ++i) {
            int new_x = frn.x + dir[i][0];
            int new_y = frn.y + dir[i][1];

            if(cost[new_x][new_y] == -1 or used[new_x][new_y]) {
                continue;
            }

            used[new_x][new_y] = true;

            if(cost[frn.x][frn.y] + 1 < cost[new_x][new_y] or !cost[new_x][new_y]) {
                q.push({new_x, new_y});
                cost[new_x][new_y] = cost[frn.x][frn.y] + 1;
            }
        }
    }
}

void print_used() {
    for(int i = 1; i <= n; ++i) {
        for(int j = 1; j <= m; ++j) {
            cout << used[i][j] << ' ';
        }

        cout << '\n';
    }

    cout << '\n';
}

void print_cost() {
    for(int i = 1; i <= n; ++i) {
        for(int j = 1; j <= m; ++j) {
            cout << cost[i][j] << ' ';
        }

        cout << '\n';
    }

    cout << '\n';
}

inline bool bfs(int min_cost) {
    q.push(paft);
    used[paft.x][paft.y] = true;
    if(cost[paft.x][paft.y] < min_cost) {
        return false;
    }

    while(!q.empty()) {
        /*if(min_cost == 5) {
            print_used();
        }*/

        Coord frn = q.front();
        q.pop();

        for(int i = 0; i < 4; ++i) {
            Coord nxt;
            nxt.x = frn.x + dir[i][0];
            nxt.y = frn.y + dir[i][1];

            if(used[nxt.x][nxt.y] or cost[nxt.x][nxt.y] == -1) {
                continue;
            }

            used[nxt.x][nxt.y] = true;

            if(cost[nxt.x][nxt.y] >= min_cost) {
                q.push(nxt);

                if(ext == nxt) {
                    return true;
                }
            }
        }
    }

    return false;
}

inline void init_q() {
    while(!q.empty()) {
        q.pop();
    }
}

int bin_search(int l, int r) {
    int med, ans = -1;

    while(l <= r) {
        med = (l + r) / 2;
        memset(used, 0, sizeof used);
        init_q();

        /*if(med == 5) {
            ///debug
            int a = 0;
            ++a;
        }*/

        if(bfs(med)) {
            /*if(med == 5) {
                print_used();
            }*/
            l = med + 1;
            ans = med;
        }
        else {
            r = med - 1;
        }
    }

    return ans;
}

int main() {
    cin >> n >> m;

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

            if(ch == 'I') {
                paft = {i, j};
            }
            else if(ch == 'D') {
                drag[drag_nr] = {i, j};
                ++drag_nr;
            }
            else if(ch == '*') {
                cost[i][j] = -1;
            }
            else if(ch == 'O') {
                ext = {i, j};
            }
        }
    }

    bord_matrix();

    /*for(int i = 1; i <= drag_nr - 1; ++i) {
        memset(used, 0, sizeof used);
        fill_dragon(drag[i]);
        //print_cost();
    }*/

    fill_dragon();
    //print_cost();
    int ans = bin_search(0, n + m + 1);

    if(ans != -1) {
        --ans;
    }

    cout << ans << '\n';
    return 0;
}