Cod sursa(job #851545)

Utilizator h2g2Ford Prefect h2g2 Data 10 ianuarie 2013 01:02:18
Problema Barbar Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.64 kb
//ideea ii asa: fac un bfs in care sa am initial in coada toate nodurile cu dragoni
//si calculez dist[i][j] = distanta pana la cel mai apropiat dragon
//apoi, trebuie sa gasesc cea mai mare distanta X
//pentru care sa pot ajunge de la I la O doar prin casute cu valori >= X
//ca sa gasesc eficient valoarea asta, o caut binar, si la fiecare pas fac un bfs (incerc sa ajung de la I la O)
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <deque>
#include <queue>
#include <stack>
#define nmax 1005
#define x first
#define y second
#define inf 1<<30
using namespace std;

struct nod {
    int x, y;
};

queue <nod> q;
char a[nmax][nmax];
bool vizitat[nmax][nmax], posibil, exista_vreo_solutie = false;
int dist[nmax][nmax];
vector <nod> ind, traseu;
int i, j, r, c, st, dr, distanta;
nod start, finish;

void init() {
    for(int i=1; i<=r; i++)
        for(int j=1; j<=c; j++)
            vizitat[i][j] = false;
}
bool valid(nod z) {
    if(z.x >= 1 && z.x <= r && z.y >= 1 && z.y <= c)
        if(a[z.x][z.y] != 'D' && a[z.x][z.y] != '*') return true;
    return false;
}

void bfs_distanta() {
    nod curent, vecin;

    while(!q.empty()) {
        curent = q.front();
        vizitat[curent.x][curent.y] = true;
        q.pop();
        traseu.push_back(curent);

        for(int i=0; i<ind.size(); i++) {
            vecin.x = curent.x + ind[i].x;
            vecin.y = curent.y + ind[i].y;
            if(valid(vecin) && !vizitat[vecin.x][vecin.y]) {
                dist[vecin.x][vecin.y] = min(dist[vecin.x][vecin.y], dist[curent.x][curent.y] + 1);
                q.push(vecin);
            }
        }
    }
}

void bfs(int distanta) {
    nod curent, vecin;

    while(!q.empty()) {
        curent = q.front();
        vizitat[curent.x][curent.y] = true;
        q.pop();

        if(curent.x == finish.x && curent.y == finish.y) {
            posibil = true;
            exista_vreo_solutie = true;
            while(!q.empty()) q.pop();
        }

        for(int i=0; i<ind.size(); i++) {
            vecin.x = curent.x + ind[i].x;
            vecin.y = curent.y + ind[i].y;
            if(valid(vecin) && !vizitat[vecin.x][vecin.y] && dist[vecin.x][vecin.y] >= distanta)
                q.push(vecin);
        }
    }

}



int main() {
	ifstream f("barbar.in");
	ofstream g("barbar.out");

    nod z;
	for(i=-1; i<=1; i++)
        for(j=-1; j<=1; j++)
            if(abs(i) != abs(j)) { z.x = i; z.y = j; ind.push_back(z); }

    f>>r>>c;
    for(i=1; i<=r; i++) {
        for(j=1; j<=c; j++) {
            f>>a[i][j];
            dist[i][j] = inf;

            if(a[i][j] == 'I') start.x = i, start.y = j;
            if(a[i][j] == 'O') finish.x = i, finish.y = j;
            if(a[i][j] == 'D') z.x = i, z.y = j, q.push(z), dist[i][j] = 0;
        }
    }

    init();
    bfs_distanta();

    /*for(i=1; i<=r; i++) {
        for(j=1; j<=c; j++) {
            if(dist[i][j]==inf) g<<"* ";
            else g<<dist[i][j]<<" ";
        }
        g<<"\n";
    }*/

    while(!q.empty()) q.pop();
    st = 0;
    dr = nmax + nmax - 1;

    while(dr - st > 1) {
        distanta = (st + dr) / 2 + (st+dr)%2;
        posibil = false;

        for(i=0; i<traseu.size(); i++) vizitat[traseu[i].x][traseu[i].y] = false;   //initializez doar nodurile vizitate, nu pe toate de fiecare data
        traseu.clear();

        q.push(start);  //bag nodul initial in coada
        bfs(distanta);

        if(posibil) st = distanta;
        else dr = distanta;
    }

    if(!exista_vreo_solutie) st = -1;

    g<<st<<"\n";




	return 0;
}