Cod sursa(job #1426028)

Utilizator RanKBrinduse Alexandru RanK Data 28 aprilie 2015 20:15:40
Problema Barbar Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.85 kb
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

#include <stdlib.h>
#include <queue>

using namespace std;

#define IN_FILE_NAME "barbar.in"
#define OUT_FILE_NAME "barbar.out"

typedef struct _POSITION
{
	int line;
	int col;
}POSITION;

int matrix[1000][1000];

#define DRAGON -5
#define WALL -1
#define CLEAR -2
#define START -3
#define STOP -4

void PrintMatrix(int n, int m)
{
	int i,j;
	for(i=0; i<n; i++)
	{
		for(j=0; j<m; j++)
		{
			char ch;
			if(matrix[i][j] == WALL)
				ch = '*';
			ch = matrix[i][j] + '0';

			printf("%c ", ch);
		}
		printf("\n");
	}
}

bool CheckIfPossible(int minDistance, int n, int m, POSITION *startPos, POSITION *stopPos)
{
	bool retVal = false;

	POSITION *newPos = new POSITION();
	newPos->line = startPos->line;
	newPos->col = startPos->col;

	queue<POSITION*> bfsQueue = queue<POSITION *>();
	bfsQueue.push(newPos);
	
	bool visited[1000][1000];
	memset(visited, false, sizeof(visited));

	while(bfsQueue.size() > 0)
	{
		POSITION *currPos = bfsQueue.front();
		bfsQueue.pop();

		int line = currPos->line;
		int col = currPos->col;
		delete currPos;

		if(line < 0 || col < 0 || line >= n || col >= m)
			continue;
		if(visited[line][col])
			continue;
		if(matrix[line][col] < minDistance)
			continue;
		if(line == stopPos->line && col == stopPos->col)
		{
			retVal = true;
			break;
		}

		visited[line][col] = true;
		POSITION *posLeft = new POSITION();
		POSITION *posRight = new POSITION();
		POSITION *posTop = new POSITION();
		POSITION *posBottom = new POSITION();

		posLeft->line = line;			posLeft->col = col - 1;
		posRight->line = line;			posRight->col = col + 1;
		posTop->line = line - 1;		posTop->col = col;
		posBottom->line = line + 1;		posBottom->col = col;

		bfsQueue.push(posLeft);
		bfsQueue.push(posRight);
		bfsQueue.push(posTop);
		bfsQueue.push(posBottom);
	}

	// clear queue
	/*while(!bfsQueue.empty())
	{
		delete bfsQueue.front();
		bfsQueue.pop();
	}*/
	
	return retVal;
}

int main()
{
	freopen(IN_FILE_NAME, "r", stdin);
	freopen(OUT_FILE_NAME, "w", stdout);

	int n,m;
	scanf("%d %d", &n, &m);

	queue<POSITION*> dragonQueue = queue<POSITION*>();

	POSITION *startPos = new POSITION();
	POSITION *stopPos = new POSITION();

	int i,j;
	for(i=0; i<n; i++)
	{
		char line[1000];
		scanf("%s", line);
		for(j=0; j<m; j++)
		{
			char ch;
			ch = line[j];
			if(ch == 'I')
			{				
				matrix[i][j] = START;
				startPos->line = i;
				startPos->col = j;				
			}
			else if(ch == 'D')
			{
				POSITION *pos = new POSITION();
				pos->line = i;
				pos->col = j;
				dragonQueue.push(pos);
				matrix[i][j] = DRAGON;
			}
			else if(ch == '*')
			{
				matrix[i][j] = WALL;
			}
			else if(ch == 'O')
			{
				matrix[i][j] = STOP;
				stopPos->line = i;
				stopPos->col = j;
			}
			else
			{
				matrix[i][j] = CLEAR;
			}
		}
	}

	// Fill the matrix with distances from dragons
	int currDistance = 0;
	int startIndex = 0;
	int stopIndex = dragonQueue.size();
	while(dragonQueue.size() > 0)
	{
		if(startIndex == stopIndex)
		{
			currDistance++;
			stopIndex = startIndex + dragonQueue.size();
		}

		POSITION *currPos = dragonQueue.front();
		dragonQueue.pop();
		startIndex++;

		int line = currPos->line;
		int col = currPos->col;

		delete currPos;
		
		if(line < 0 || col < 0 || line >= n || col >= m || matrix[line][col] >= 0)
			continue;
		if(matrix[line][col] == WALL)
			continue;

		matrix[line][col] = currDistance;

		POSITION *posLeft = new POSITION();
		POSITION *posRight = new POSITION();
		POSITION *posTop = new POSITION();
		POSITION *posBottom = new POSITION();

		posLeft->line = line;			posLeft->col = col - 1;
		posRight->line = line;			posRight->col = col + 1;
		posTop->line = line - 1;		posTop->col = col;
		posBottom->line = line + 1;		posBottom->col = col;

		dragonQueue.push(posLeft);
		dragonQueue.push(posRight);
		dragonQueue.push(posTop);
		dragonQueue.push(posBottom);
	}

	int maxMinDistance = min(matrix[startPos->line][startPos->col], matrix[stopPos->line][stopPos->col]);
	int minMinDistance = 0;

	// Binary Search
	int max = 0;
	while(maxMinDistance > minMinDistance)
	{
		int mid = (maxMinDistance + minMinDistance) / 2;
		if(CheckIfPossible(mid, n, m, startPos, stopPos))
		{
			if(minMinDistance == mid)
			{
				if(CheckIfPossible(maxMinDistance, n, m, startPos, stopPos))
				{
					minMinDistance = maxMinDistance;
				}
				else
				{
					maxMinDistance = minMinDistance;
				}
			}
			else
			{
				minMinDistance = mid;
			}
		}
		else
		{	
			if(maxMinDistance == mid)
			{
				int a = 0;
				int b = 4 / a;
			}
			maxMinDistance = mid;
		}
	}
	if(maxMinDistance == 0)
	{
		maxMinDistance = -1;
	}
	//PrintMatrix(n,m);
	printf("%d", maxMinDistance);

	return 0;
}