Cod sursa(job #2242488)

Utilizator Mada2003Madalina Scarlat Mada2003 Data 18 septembrie 2018 19:27:52
Problema Barbar Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.19 kb
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define NMAX 1000
#define CHUNK (1 << 20)

char buf[CHUNK];
size_t bpos, qh, qt;

static struct point {
    int l;
    int c;
} q[NMAX*NMAX], dirs[] = {{-1, 0}, {+1, 0}, {0, -1}, {0, +1}};

static inline int read_int(void)
{
    int x = 0;

    while ('0' <= buf[bpos] && buf[bpos] <= '9') {
        x = x * 10 + (buf[bpos] - '0');
        bpos++;
    }

    bpos++;
    return x;
}

int main(void)
{
    int dist[NMAX][NMAX];
    char visited[NMAX][NMAX], dungeon[NMAX][NMAX];
    int i, j, l, c, nl, nc, step, lower = 0, res;
    struct point in, p;

    freopen("barbar.in", "r", stdin);
    freopen("barbar.out", "w", stdout);

    read(STDIN_FILENO, buf, CHUNK);

    l = read_int();
    c = read_int();

    res = INT_MAX;

    for (i = 0; i < l; i++) {
        for (j = 0; j < c; j++) {
            dist[i][j] = INT_MAX;
            if ((dungeon[i][j] = buf[bpos++]) == 'D') {
                q[qt].l = i;
                q[qt].c = j;
                dist[i][j] = 0;
                visited[i][j] = 1;
                qt++;
            } else if (dungeon[i][j] == 'I') {
                in.l = i;
                in.c = j;
            }
        }

        bpos++;
    }

    while (qh < qt) {
        p = q[qh++];
        for (i = 0; i < 4; i++) {
            nl = p.l + dirs[i].l;
            nc = p.c + dirs[i].c;
            if (0 <= nl && nl < l && 0 <= nc && nc < c &&
                    dungeon[nl][nc] != '*' && !visited[nl][nc]) {
                if (dist[p.l][p.c] + 1 < dist[nl][nc]) {
                    dist[nl][nc] = dist[p.l][p.c] + 1;
                    visited[nl][nc] = 1;
                    q[qt].l = nl;
                    q[qt].c = nc;
                    qt++;
                }
            }
        }
    }

    res = -1;

    for (step = 1 << 16; step >= 0; step >>= 1) {

        if (dist[in.l][in.c] < lower + step) {
            continue;
        }

        memset(visited, 0x00, sizeof visited);
        qh = qt = 0;
        q[qt].l = in.l;
        q[qt].c = in.c;
        visited[q[qt].l][q[qt].c] = 1;
        qt++;

        while (qh < qt) {
            p = q[qh++];
            for (i = 0; i < 4; i++) {
                nl = p.l + dirs[i].l;
                nc = p.c + dirs[i].c;
                if (0 <= nl && nl < l && 0 <= nc && nc < c &&
                        visited[nl][nc] == '\0' &&
                        dungeon[nl][nc] != '*' && dungeon[nl][nc] != 'D') {
                    if (dist[nl][nc] >= lower + step) {
                        visited[nl][nc] = 1;
                        q[qt].l = nl;
                        q[qt].c = nc;
                        qt++;

                        if (dungeon[nl][nc] == 'O') {
                            if (lower + step >= res) {
                                res = lower + step;
                                lower += step;
                            }
                        }
                    }
                }
            }
        }

        if (step == 0) {
            step = -1;
        }
    }

    printf("%d", res);

    return 0;
}