Cod sursa(job #1604076)

Utilizator stoianmihailStoian Mihail stoianmihail Data 17 februarie 2016 22:25:36
Problema Barbar Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.1 kb
#include <iostream>
#include <fstream>
#include <queue>
#include <stdio.h>
#include <string.h>
#include <assert.h>

#define NR_MAX 1000

using namespace std;

typedef struct {
    int l;
    int c;
} poz;

queue <poz> lee;
poz start, finish;

int n, m;
int rasp = 1;
int mtr[1 + NR_MAX + 1][1 + NR_MAX + 1];
bool mtr2[1 + NR_MAX + 1][1 + NR_MAX + 1], mtrAux[1 + NR_MAX + 1][1 + NR_MAX + 1];
int veciniL[] = {0, -1, 0, 1, -1, -1, 1, 1};
int veciniC[] = {-1, 0, 1, 0, -1, 1, 1, -1};


bool fillVal(int val, int l, int c) {

    mtr2[l][c] = 1;
    for (int i = 0; i < 4; i++) {
        if (mtr2[finish.l][finish.c] == 1)
            return 1;
        if (mtr[l + veciniL[i]][c + veciniC[i]] >= val && mtr2[l + veciniL[i]][c + veciniC[i]] == 0)
            fillVal(val, l + veciniL[i], c + veciniC[i]);
    }

    return 0;
}

bool fill(int val, int l, int c) {
    fillVal(val, start.l, start.c);
    return (bool)mtr2[finish.l][finish.c];
}

int cautBin() {
    int i = 0, ok = 0;
    int pas = 1 << 10;
    bool stop = false;
    while (!stop) {
        ok = fillVal(i + pas + 1, start.l, start.c);
        if ((i + pas <= 2000) && ok == 1 ) {
            if (pas + i == 0)
                rasp = 0;
            i += pas;
        // curatare

        }
        if (pas == 0)
            stop = true;

        pas /= 2;
        memcpy(mtr2, mtrAux, (1 + NR_MAX + 1)*(1 + NR_MAX + 1));

    }
    return i;
}

int main() {
    ifstream file_in ("barbar.in");
    ofstream file_out ("barbar.out");

    char c;
    int sol;

    /// Citirea datelor
    file_in >> n >> m;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            file_in >> c;
            if (c == '.') {
                mtr[i][j] = 0;
            } else if (c == '*') {
                mtr[i][j] = -1;
            } else if (c == 'D') {
                mtr[i][j] = 1;
                lee.push((poz){i, j});
            } else if (c == 'I') {
                start.l = i;
                start.c = j;
            } else if (c == 'O') {
                finish.l = i;
                finish.c = j;
            }
        }
    }
    // bordare
    for (int i = 0; i <= n + 1; i++) {
        mtr[i][0] = mtr[i][m + 1] = -1;
    }

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

    /// Calcularea solutiei

    // Lee
    int lact, cact, lvec, cvec;
    while(!lee.empty()) {
        lact = lee.front().l;
        cact = lee.front().c;
        lee.pop();
        for (int i = 0; i < 4; i++) {
            lvec = lact + veciniL[i];
            cvec = cact + veciniC[i];
            if (mtr[lvec][cvec] == 0) {
                lee.push((poz){lvec, cvec});
                mtr[lvec][cvec] = mtr[lact][cact] + 1;
            }
        }
    }

    /*for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            file_out << mtr[i][j] << " ";
        }
        file_out << "\n";
    }*/

    /// Afisarea solutiei

    sol = cautBin();
    if (rasp == 0) {
        //assert(0);
        file_out << -1;
    } else if (sol == 0) {
        file_out << -1;
        //assert(0);
    } else {
        file_out << sol;
    }

    return 0;
}