Cod sursa(job #483627)

Utilizator dcm9000Dinu Cristian Mircea - UPB dcm9000 Data 9 septembrie 2010 14:34:28
Problema Barbar Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.66 kb
#include <iostream>
#include <algorithm>
#include <fstream>
#include <string>
#include <map>

using namespace std;

#define FILE_IN "barbar.in"
#define FILE_OUT "barbar.out"

#define STRIDE 1024

int R, C;
char MAP[1024*STRIDE];
short DIST[1024*STRIDE];
int NOD_IN;
int NOD_OUT;

void incarcaHarta()
{
	ifstream fisIn(FILE_IN);
	fisIn >> R >> C;
	for (int i=0; i<R; i++)
	{
		int baza = (i+1)*STRIDE;
		
		fisIn >> (MAP+baza+1);
		MAP[baza] = '*';
		MAP[baza+C+1] = '*';
		MAP[baza+C+2] = 0;

		char* pos = strchr(MAP+baza, 'I');
		if (pos) NOD_IN = pos-MAP;

		pos = strchr(MAP+baza, 'O');
		if (pos) NOD_OUT = pos-MAP;
	}

	memset(MAP, '*', C+2); MAP[C+2] = 0;
	memset(MAP+(R+1)*STRIDE, '*', C+2); MAP[(R+1)*STRIDE+C+2] = 0;
}

static inline int min(int a, int b)
{
	return a<b ? a : b;
}

void calcDist()
{
	int ptr, ptrMax;
	
	memset(DIST, 0x3F, sizeof(short)*STRIDE*(R+2));
	
	for (int i=1; i<=R; i++)
	{
		int baza = i*STRIDE;

		for (ptr=baza+1, ptrMax=baza+C; ptr<=ptrMax; ptr++)
			if (MAP[ptr] == 'D')
				DIST[ptr] = 0;
			else if (MAP[ptr] == '*')
				DIST[ptr] = 0x3F3F;
			else
				DIST[ptr] = min(DIST[ptr-1], DIST[ptr-STRIDE])+1;
		
		for (ptr=baza+C, ptrMax=baza+1; ptr>=ptrMax; ptr--)
			if (MAP[ptr] != '*')
				DIST[ptr] = min(DIST[ptr], DIST[ptr+1]+1);
	}

	for (int i=R; i>=1; i--)
	{
		int baza = i*STRIDE;

		for (ptr=baza+1, ptrMax=baza+C; ptr<=ptrMax; ptr++)
			if (MAP[ptr] != '*')
				DIST[ptr] = min(DIST[ptr], DIST[ptr+STRIDE]+1);
	}
}

void curataHarta()
{
	int ptr, ptrMax;
	
	for (int i=1; i<=R; i++)
		for (ptr=i*STRIDE+1,ptrMax=i*STRIDE+C; ptr<=ptrMax; ptr++)
			switch (MAP[ptr])
			{
				case 'I': case 'O': case 'D': MAP[ptr] = '.'; break;
			}
}

int main()
{
	incarcaHarta();
	calcDist();
	curataHarta();

	multimap<short, int> coada;
	multimap<short, int>::iterator it;

	coada.insert(pair<short,int>(DIST[NOD_IN], NOD_IN));
	MAP[NOD_IN] = 'X';

	short best = 10000;
	while (!coada.empty())
	{
		it = --coada.end();
		short dist = it->first;
		int nod = it->second;
		coada.erase(it);

		if (dist < best) best = dist;
		
		if (nod == NOD_OUT) break;

		if (MAP[nod-STRIDE] == '.') { coada.insert(pair<short,int>(DIST[nod-STRIDE], nod-STRIDE)); MAP[nod-STRIDE]='X'; }
		if (MAP[nod+STRIDE] == '.') { coada.insert(pair<short,int>(DIST[nod+STRIDE], nod+STRIDE)); MAP[nod+STRIDE]='X'; }
		if (MAP[nod-1] == '.') { coada.insert(pair<short,int>(DIST[nod-1], nod-1)); MAP[nod-1]='X'; }
		if (MAP[nod+1] == '.') { coada.insert(pair<short,int>(DIST[nod+1], nod+1)); MAP[nod+1]='X'; }
	}

	ofstream fisOut(FILE_OUT);
	fisOut << ((MAP[NOD_OUT] == 'X') ? best : -1);
}