Cod sursa(job #2298190)

Utilizator dey44andIoja Andrei-Iosif dey44and Data 7 decembrie 2018 17:55:34
Problema Barbar Scor 80
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.94 kb
#include <fstream>
#include <vector>
//#include <queue>

#define input "barbar.in"
#define output "barbar.out"
#define MATRIX_SIZE 1005

using namespace std;

ifstream in(input);
ofstream out(output);

//-----Queue declares Area-----

struct inf
{
	int x, y;
};
struct nod
{
	inf info;
	nod *next;
};
typedef nod* queue;

void Push_Back(queue &coada, queue &tail, inf informatii)
{
	queue aux = new nod;
	aux->info = informatii;
	if (!coada) coada = aux, tail = coada;
	else
	{
		tail->next = aux;
		tail = tail->next;
	}
}

void Pop_Front(queue &coada, queue &tail)
{
	if (!coada && !tail) return;
	if (coada == tail)
	{
		queue aux = coada;
		coada = tail = NULL;
		delete aux;
		return;
	}
	// Daca niciunul din cazurile exceptate nu se regaseste, vom elimina 
	queue aux = coada;
	coada = coada->next;
	delete aux;
}

bool Empty(queue coada, queue tail)
{
	if (coada == tail && coada == NULL) return true;
	return false;
}

inf Get_Front(queue coada, queue tail)
{
	return coada->info;
}

//-----End Queue declares Area-----

int dx[] = { -1, 1, 0, 0 };
int dy[] = { 0, 0, -1, 1 };

queue coada, tail;
int N, M, map[MATRIX_SIZE][MATRIX_SIZE], dragon_distance[MATRIX_SIZE][MATRIX_SIZE];
inf start_point, stop_point;

bool OK_Dragon(int x, int y)
{
	if (x < 1 || x > N || y < 1 || y > M)
		return false;
	if (dragon_distance[x][y])
		return false;
	return true;
}
bool OK(int x, int y)
{
	if (x < 1 || x > N || y < 1 || y > M)
		return false;
	if (map[x][y] > 0 || map[x][y] == -1)
		return false;
	return true;
}

void Read_Data()
{
	in >> N >> M;
	for (int i = 1; i <= N; i++)
	for (int j = 1; j <= M; j++)
	{
		char c;
		in >> c;
		if (c == 'I') start_point = { i, j };
		else if (c == 'O') stop_point = { i, j };
		else if (c == 'D') Push_Back(coada, tail, { i, j }), dragon_distance[i][j] = 1;
		else if (c == '*') map[i][j] = -1;
	}
}

void Lee_Dragon()
{
	while (!Empty(coada, tail))
	{
		inf date = Get_Front(coada, tail);
		Pop_Front(coada, tail);
		for (int d = 0; d < 4; d++)
		{
			int x_new = date.x + dx[d];
			int y_new = date.y + dy[d];
			if (OK_Dragon(x_new, y_new))
			{
				dragon_distance[x_new][y_new] = dragon_distance[date.x][date.y] + 1;
				Push_Back(coada, tail, { x_new, y_new });
			}
		}
	}
}

void Print_Sol_Dragon()
{
	for (int i = 1; i <= N; i++)
	{
		for (int j = 1; j <= M; j++)
			out << dragon_distance[i][j] << " ";
		out << "\n";
	}
	out << "\n";
}

void Print_Sol()
{
	for (int i = 1; i <= N; i++)
	{
		for (int j = 1; j <= M; j++)
			out << map[i][j] << " ";
		out << "\n";
	}
	out << "\n";
}

void Decrease_by_one()
{
	for (int i = 1; i <= N; i++)
	for (int j = 1; j <= M; j++)
		dragon_distance[i][j]--;
}

void Redo()
{
	for (int i = 1; i <= N; i++)
	for (int j = 1; j <= M; j++)
	if (map[i][j] != -1) map[i][j] = 0;
}

bool Lee(int val)
{
	if (dragon_distance[start_point.x][start_point.y] < val) return false;
	map[start_point.x][start_point.y] = 1;
	Push_Back(coada, tail, start_point);
	while (!Empty(coada, tail))
	{
		inf date = Get_Front(coada, tail);
		Pop_Front(coada, tail);
		for (int d = 0; d < 4; d++)
		{
			int x_new = date.x + dx[d];
			int y_new = date.y + dy[d];
			if (OK(x_new, y_new) && dragon_distance[x_new][y_new] >= val)
			{
				map[x_new][y_new] = map[date.x][date.y] + 1;
				Push_Back(coada, tail, { x_new, y_new });
			}
		}
	}
	if (map[stop_point.x][stop_point.y] > 0) return true;
	return false;
}

void Binary_Search()
{
	int optim = -1;
	int st = 0, dr = 1000;
	while (st <= dr)
	{
		int mid = (st + dr) / 2;
		bool valid = Lee(mid);
		Redo();
		if (valid) optim = mid, st = mid + 1;
		else dr = mid - 1;
	}
	out << optim << "\n";
}

void Control_Function()
{
	Read_Data();
	// Dragons files
	Lee_Dragon();
	Decrease_by_one();
	//Print_Sol_Dragon();
	// Cautarea solutiei
	Binary_Search();
}

int main()
{
	Control_Function();
	return 0;
}