Cod sursa(job #1426172)

Utilizator tamionvTamio Vesa Nakajima tamionv Data 29 aprilie 2015 03:40:52
Problema Barbar Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.25 kb
#include <fstream>
#include <utility>
#include <queue>
using namespace std;
 
struct comanda{
	pair<int, int> p;
	int val; };
 
constexpr bool operator<(const comanda& lhs, const comanda& rhs){
	return lhs.val < rhs.val; }
 
template <typename T>
class mat{
	T* buf;
public:
	const int n, m;
	constexpr mat(const int N, const int M):
		buf(new T[N*M]), n(N), m(M){}
	~mat(){
		delete[] buf; }
	constexpr T& la(const int x, const int y){
		return buf[x*m + y]; }
	constexpr T& operator[](const pair<int, int>& p){
		return la(p.first, p.second); }
	constexpr T& operator[](const comanda& c){
		return (*this)[c.p]; }
	void edge(const int val){
		for(int i = 0; i < n; ++i){
			la(i, 0) = val;
			la(i, m-1) = val; }
		for(int i = 0; i < m; ++i){
			la(0, i) = val;
			la(n-1, i) = val; } } };
 
constexpr int gol = -3, blocat = -4, dl[] = {0, 1, 0, -1}, dc[] = {1, 0, -1, 0},
	inf = 1000001;
 
void citeste_mat(ifstream& f, const int n, const int m, mat<int>& distdrag, mat<int>& distpaft, queue<pair<int, int> >& dragoni,
	pair<int, int>& paftenie, pair<int, int>& iesire){
	char* buf = new char[m+1];
	for(int i = 1; i <= n; ++i){
		f.read(buf, m+1);
		for(int j = 1; j <= m; ++j){
			switch(buf[j]){
			case '.':
				distdrag.la(i, j) = gol;
				distpaft.la(i, j) = -inf;
				break;
			case '*':
				distdrag.la(i, j) = blocat;
				distpaft.la(i, j) = blocat;
				break;
			case 'D':
				distdrag.la(i, j) = 0;
				distpaft.la(i, j) = -inf;
				dragoni.emplace(i, j);
				break;
			case 'I':
				distdrag.la(i, j) = gol;
				distpaft.la(i, j) = -inf;
				paftenie.first = i;
				paftenie.second = j;
				break;
			case 'O':
				distdrag.la(i, j) = gol;
				distpaft.la(i, j) = -inf;
				iesire.first = i;
				iesire.second = j;
				break; } } }
	delete[] buf; }
 
void fa_distdrag(mat<int>& distdrag, queue<pair<int, int> >& dragoni){
	pair<int, int> cur, next;
	while(!dragoni.empty()){
		cur = dragoni.front();
		dragoni.pop();
		for(int i = 0; i < 4; ++i){
			next.first = cur.first + dl[i];
			next.second = cur.second + dc[i];
			if(distdrag[next] == gol){
				distdrag[next] = distdrag[cur] + 1;
				dragoni.push(next); } } } }
 
bool fa_distpaft(mat<int>& distpaft, const mat<int>& distdrag,
	const pair<int, int>& paftenie, const pair<int, int>& iesire){
	distpaft[paftenie] = distdrag[paftenie];
 
	priority_queue<comanda> de_viz;
	de_viz.push(comanda{paftenie, distpaft[paftenie]});
	comanda cur, next;
	while((!de_viz.empty()) && cur.p != iesire){
		cur = de_viz.top();
		de_viz.pop();
		if(distpaft[cur] == cur.val){
			for(int i = 0; i < 4; ++i){
				next.p.first = cur.p.first + dl[i];
				next.p.second = cur.p.second + dc[i];
				next.val = min(cur.val, distdrag[next]);
				if(distpaft[next] != blocat && distpaft[next] < next.val){
					distpaft[next] = next.val;
					de_viz.push(next); } } } } }
 
int main(){
	ifstream f("barbar.in");
	ofstream g("barbar.out");
	int n, m;
	f >> n >> m;
	mat<int> distdrag(n+2, m+2), distpaft(n+2, m+2);
	distdrag.edge(blocat);
	distpaft.edge(blocat);
	queue<pair<int, int> > dragoni;
	pair<int, int> paftenie, iesire;
	citeste_mat(f, n, m, distdrag, distpaft, dragoni, paftenie, iesire);
 
	fa_distdrag(distdrag, dragoni);
 
	fa_distpaft(distpaft, distdrag, paftenie, iesire);
 
	if(distpaft[iesire] < 0){
		g << "-1"; }
	else{
		g << distpaft[iesire]; }
	return 0; }