Cod sursa(job #1400653)

Utilizator g3ppyStoian Vlad g3ppy Data 25 martie 2015 13:12:10
Problema Barbar Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.03 kb
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>

#define NMAX 1005

using namespace std;

bool wall[NMAX][NMAX];
bool visited[NMAX][NMAX];
char dragon_map[NMAX][NMAX];
int distance_map[NMAX][NMAX];

int move_x[4] = { 1, 0, -1, 0 };
int move_y[4] = { 0, 1, 0, -1 };

struct point {
    point(int _x, int _y):x(_x),y(_y),distance(0){};
    point():x(0),y(0),distance(0){};

    void set_coords(short _x, short _y) { this->x = _x; this->y = _y; }
    void print() { printf("Point: x: %d, y: %d\n", this->x, this->y); }

    int x, y;
    int distance;
};

int N, M;
point start_point, end_point;

void print_distance_map() {
    for (int i = 0; i <= N + 1; i++) {
        for (int j = 0; j <= M + 1; j++) {
            cout << distance_map[i][j];
        }
        cout << endl;
    }
}

void print_wall() {
    for (int i = 0; i <= N + 1; i++) {
        for (int j = 0; j <= M + 1; j++) {
            if (wall[i][j]) { cout << "#"; }
            else { cout << "."; }
        }
        cout << endl;
    }
}

void print_visited() {
    for (int i = 0; i <= N + 1; i++) {
        for (int j = 0; j <= M + 1; j++) {
            if (visited[i][j]) { cout << "#"; }
            else { cout << "."; }
        }
        cout << endl;
    }
}

void reset_visited() {
    for (int i = 0; i <= N + 1; i++) {
        for (int j = 0; j <= M + 1; j++) {
            visited[i][j] = false;
        }
    }
}

struct compare_point_distance {
    bool operator() (const point& lhs, const point&rhs) const {
        return lhs.distance < rhs.distance;
    }
};

int main() {

    if (freopen("barbar.in", "r", stdin) == NULL ||
        freopen("barbar.out", "w", stdout) == NULL) return 1;
    cin >> N >> M;

    queue<point> q;

    for (int i = 0; i <= N + 1; i++) wall[i][0] = wall[i][M + 1] = true;
    for (int j = 0; j <= M + 1; j++) wall[0][j] = wall[N + 1][j] = true;

    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            char c;
            cin >> c;
            dragon_map[i][j] = c;

            if (c == '*') { wall[i][j] = true; }
            if (c == 'I') { start_point.set_coords(i, j); }
            if (c == 'O') { end_point.set_coords(i, j); }
            if (c == 'D') {
                point dragon_point(i, j);
                visited[i][j] = true;
                q.push(dragon_point);
            };
        }
    }

    while(!q.empty()) {
        point current_point = q.front();
        q.pop();
        //current_point.print();
        distance_map[current_point.x][current_point.y] = current_point.distance;

        for (int i = 0; i < 4; i++) {
            point new_point(current_point.x + move_x[i], current_point.y + move_y[i]);
            new_point.distance = current_point.distance + 1;

            if (!wall[new_point.x][new_point.y] && !visited[new_point.x][new_point.y]) {
                visited[new_point.x][new_point.y] = true;
                q.push(new_point);

                distance_map[new_point.x][new_point.y] = new_point.distance;
            }
        }
    }

    reset_visited();
    priority_queue<point, vector<point>, compare_point_distance> pq;
    start_point.distance = distance_map[start_point.x][start_point.y];
    pq.push(start_point);

    while(!pq.empty()) {
        point current_point = pq.top();
        pq.pop();

        if (current_point.x == end_point.x && current_point.y == end_point.y) {
                printf("%d\n", current_point.distance);
                break;
        }

        for (int i = 0; i < 4; i++) {
            point new_point(current_point.x + move_x[i], current_point.y + move_y[i]);
            new_point.distance = min(current_point.distance, distance_map[new_point.x][new_point.y]);

            if (!wall[new_point.x][new_point.y] && !visited[new_point.x][new_point.y]) {
                visited[new_point.x][new_point.y] = true;
                pq.push(new_point);
            }
        }
    }

    return 0;
}