Cod sursa(job #1492381)

Utilizator aimrdlAndrei mrdl aimrdl Data 27 septembrie 2015 17:23:05
Problema Barbar Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.5 kb
#include <stdio.h>
#include <queue>
#include <vector>
#include <algorithm>

#define IN -1
#define OUT -2
#define DRAGON 0
#define FREE -3
#define BLOCKED -4

using namespace std;

typedef struct {
	int i, j;
	int d;
} TPos;

typedef struct compare {
	bool operator () (const TPos a, const TPos b) {
		return a.d < b.d;
	}
} compare;

int R, C, Ii, Ij, m = 99999999, reached;
int M[1005][1005];
vector <TPos> H;

bool comp (TPos a, TPos b) {
	return (a.d < b.d) ? true : false;
}

void read() {
	scanf("%d %d\n", &R, &C);
	
	char buffer[1005];
	
	for (int i = 0; i < R; ++i) {
		fgets(buffer, 1005, stdin);
		for (int j = 0; j < C; ++j) {
			switch (buffer[j]) {
				case '.': M[i][j] = FREE; break;
				case 'D': M[i][j] = DRAGON; break;
				case '*': M[i][j] = BLOCKED; break;
				case 'O': M[i][j] = OUT; break; 
				case 'I': {
					M[i][j] = IN;
					Ii = i; Ij = j;
					break;
				}
				default: break;
			}
		}
	}
}

int findDist (int i, int j) {	
	int dist[1005][1005] = {{0}};
	dist[i][j] = 1;
	
	queue < pair <int, int> > Q;
	Q.push(make_pair(i, j));
	
	while (!Q.empty()) {
		auto c = Q.front();
		if (M[c.first][c.second] == DRAGON) return dist[c.first][c.second]-1;
		
		if (c.first > 0 && !dist[c.first-1][c.second] && M[c.first-1][c.second] > BLOCKED) {
			dist[c.first-1][c.second] = dist[c.first][c.second] + 1;
			Q.push(make_pair(c.first-1, c.second));
		}
		
		if (c.first < R-1 && !dist[c.first+1][c.second] && M[c.first+1][c.second] > BLOCKED) {
			dist[c.first+1][c.second] = dist[c.first][c.second] + 1;
			Q.push(make_pair(c.first+1, c.second));
		}
			
		if (c.second > 0 && !dist[c.first][c.second-1] && M[c.first][c.second-1] > BLOCKED) {
			dist[c.first][c.second-1] = dist[c.first][c.second] + 1;
			Q.push(make_pair(c.first, c.second - 1));
		}
		
		if (c.second < C-1 && !dist[c.first][c.second+1] && M[c.first][c.second+1] > BLOCKED) {
			dist[c.first][c.second+1] = dist[c.first][c.second] + 1;
			Q.push(make_pair(c.first, c.second + 1));
		}
		Q.pop();
	}
	
	return -999; //shouldn't happen
}		
	
int solve () {
	TPos init = {Ii, Ij, 999};
	H.push_back(init);
	push_heap(H.begin(), H.end(), compare());
	
	while (!H.empty()) {
		auto c = H.front();
		if (c.d < m) m = c.d;
		//printf("%d %d %d\n", c.i, c.j, c.d);
		pop_heap(H.begin(), H.end(), comp);
		H.pop_back();
		
		if (c.i > 0) {
			if (M[c.i-1][c.j] == OUT) {
				return m;
			}	else if (M[c.i-1][c.j] == FREE) {
				M[c.i-1][c.j] = findDist(c.i-1, c.j);
				TPos temp = {c.i-1, c.j, M[c.i-1][c.j]};
				H.push_back(temp), push_heap(H.begin(), H.end(), compare());
			}
		}
		
		if (c.i < R-1) {
			if (M[c.i+1][c.j] == OUT) {
				return m;
			}	else if (M[c.i+1][c.j] == FREE) {
				M[c.i+1][c.j] = findDist(c.i+1, c.j);
				TPos temp = {c.i+1, c.j, M[c.i+1][c.j]};
				H.push_back(temp), push_heap(H.begin(), H.end(), compare());
			}
		}
		
		if (c.j > 0) {
			if (M[c.i][c.j-1] == OUT) {
				return m;
			} else if (M[c.i][c.j-1] == FREE) {
				M[c.i][c.j-1] = findDist(c.i, c.j-1);
				TPos temp = {c.i, c.j-1, M[c.i][c.j-1]};
				H.push_back(temp), push_heap(H.begin(), H.end(), compare());
			}
		}
		
		if (c.j < C-1) {
			if (M[c.i][c.j+1] == OUT) {
				return m;
			} else if (M[c.i][c.j+1] == FREE) {
				M[c.i][c.j+1] = findDist(c.i, c.j+1);
				TPos temp = {c.i, c.j+1, M[c.i][c.j+1]};
				H.push_back(temp), push_heap(H.begin(), H.end(), compare());
			}
		}
	}
	
	return -1;
}
		


int main (void) {
	freopen("barbar.in", "r", stdin);
	freopen("barbar.out", "w", stdout);
	
	read();
	
	make_heap(H.begin(), H.end(), compare());
	
	printf("%d", solve());
	
	return 0;
}