Cod sursa(job #1615024)

Utilizator BrandonChris Luntraru Brandon Data 26 februarie 2016 13:03:31
Problema Barbar Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.95 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;
    }
};

priority_queue <PrioQ, vector <PrioQ>, cmp> prio_q;
queue <Coord> q;

Coord paft, drag[1005], 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(Coord drg) {
    cost[drg.x][drg.y] = 1;
    q.push(drg);
    used[drg.x][drg.y] = true;

    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;

    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(bfs(med)) {
            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);
        bord_matrix();
        fill_dragon(drag[i]);
        //print_cost();
    }


    cout << bin_search(1, 1500) << '\n';
    return 0;
}