Cod sursa(job #2784138)

Utilizator vali_27Bojici Valentin vali_27 Data 15 octombrie 2021 20:49:35
Problema Barbar Scor 60
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.51 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <climits>
#include <set>

int n, m, mat[1000][1000];
std::pair<int, int> start;
std::pair<int, int> end;
void citire() {
	std::ifstream f("barbar.in");
	f >> n >> m;
	for (int i = 0; i < n; ++i) {
		std::string in;
		f >> in;
		for (int j = 0; j < m; ++j) {
			if (in[j] == 'I') start = { i,j };
			else
				if (in[j] == 'O') end = { i,j };
				else
					if (in[j] == 'D') mat[i][j] = -1;
					else if (in[j] == '*') mat[i][j] = -2;
		}
	}
}

bool ok(int i, int j) {
	return i >= 0 && i < n&& j >= 0 && j < m;
}

void drumuri() {
	std::queue<std::pair<int,int> > q;
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < m; ++j)
			if (mat[i][j] == -1)q.push({ i,j }), mat[i][j] = 1;
	}

	int di[] = { 0, 0, 1, -1 };
	int dj[] = { 1, -1, 0, 0 };
	while (!q.empty()) {
		auto top = q.front();
		q.pop();
		for (int k = 0; k <= 3; k++)
		{
			int ni = di[k] + top.first;
			int nj = dj[k] + top.second;
			if (ok(ni, nj)) {
				if (mat[ni][nj] == 0 || 1 + mat[top.first][top.second] < mat[ni][nj]) {
					q.push({ ni, nj });
					mat[ni][nj] = 1 + mat[top.first][top.second];
				}
			}
		}
	}

	for (int i = 0; i < n; ++i) 
		for (int j = 0; j < m; ++j)
			mat[i][j]--; // -1 ca sa fie dragon pe 0 
	
	mat[start.first][start.second] = INT_MAX;
	mat[end.first][end.second] = INT_MAX;
}

void print() {
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < m; ++j)
			if (std::make_pair(i, j) == start || std::make_pair(i, j) == end)
				std::cout << "# ";
			else 
				std::cout << mat[i][j] << ' ';
		std::cout << "\n";
	}
	std::cout << "\n";
}

bool check(int val) {
	std::queue<std::pair<int, int> > q;
	std::set<std::pair<int, int>>used;
	used.insert(start);
	q.push(start);

	int di[] = { 0, 0, 1, -1 };
	int dj[] = { 1, -1, 0, 0 };

	while (!q.empty()) {
		auto top = q.front();
		q.pop();
		if (top == end)return 1;

		for (int k = 0; k <= 3; k++)
		{
			int ni = di[k] + top.first;
			int nj = dj[k] + top.second;
			if (ok(ni, nj) && mat[ni][nj] >= val && used.find({ ni,nj }) == used.end() ) {
				q.push({ ni, nj });
				used.insert({ ni, nj });
			}
		}
	}
	return 0;
}

int cauta() {
	int ans = 0;
	int max_step = (1 << 30);
	while (max_step) {
		if (check(ans + max_step))
			ans += max_step;
		max_step /= 2;
	}
	return ans > 0 ? ans : -1;
}

int main()
{
	citire();
	//print();
	drumuri();
	//print();

	std::ofstream g("barbar.out");
	g << cauta();
}