Cod sursa(job #1613210)

Utilizator theodor.moroianuTheodor Moroianu theodor.moroianu Data 25 februarie 2016 11:34:58
Problema Barbar Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.36 kb
#include <fstream>
#include <vector>
using namespace std;

bool liber[1010][1010];
short dmin[1010][1010];

int n, m, dx, dy; /// dx & dy = destination
vector <pair<short int, short int> > dragoni[2010];
vector <pair<short int, short int> > fmin[2010];

void calc_dragoni();

int find_best(int max);
int minim(int x, int y);


int main() {
	ifstream in("barbar.in");
	in >> n >> m;
	char c;
	int plecx, plecy;

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			in >> c;
			if (c == '*') {
				liber[i][j] = 1;
			}
			if (c == 'D') {
				liber[i][j] = 1;
				dragoni[0].push_back({ i, j });
			}
			if (c == 'I') {
				plecx = i;
				plecy = j;
			}
			if (c == 'O') {
				dx = i;
				dy = j;
			}
		}
	}
	calc_dragoni();

	liber[plecx][plecy] = 1;

	fmin[dmin[plecx][plecy]].push_back({ plecx, plecy });

	in.close();

	for (int i = 0; i <= n; i++)
		liber[i][0] = liber[i][m + 1] = 1;

	for (int i = 0; i <= m; i++)
		liber[0][i] = liber[n + 1][i] = 1;

	ofstream out("barbar.out");

	out << find_best(dmin[plecx][plecy]);
}


int find_best(int max) { /// de unde incepem sa cautam
	for (int i = max; i > 0; --i) { /// pt toate drumurile minime
		for (int j = 0; j < fmin[i].size(); j++) {
			if (fmin[i][j].first == dx && fmin[i][j].second == dy)
				return i;
			for (int q = -1; q <= 1; q++) {
				for (int z = -1; z <= 1; z++) {
					if (z != 0 && q != 0)
						continue;
					if (liber[fmin[i][j].first + q][fmin[i][j].second + z])
						continue;
					liber[fmin[i][j].first + q][fmin[i][j].second + z] = 1;
					fmin[minim(i, dmin[fmin[i][j].first + q][fmin[i][j].second + z])].push_back({ fmin[i][j].first + q, fmin[i][j].second + z });
				}
			}
		}
	}
	return -1;
}


void calc_dragoni() {
	for (int i = 0; i < 2010; i++) {
		if (dragoni[i].size() == 0)
			break;
		for (auto j : dragoni[i]) {
			for (int q = -1; q < 2; q++) {
				for (int z = -1; z < 2; z++) {
					if (z != 0 && q != 0)
						continue;
					if (j.first + q >= 1 && j.first + q <= n && j.second + z >= 1 && j.second + z <= m && !liber[j.first + q][j.second + z] && dmin[j.first + q][j.second + z] == 0) {
						dmin[j.first + q][j.second + z] = i + 1;
						dragoni[i + 1].push_back({ j.first + q, j.second + z });
					}
				}
			}
		}
	}
}

int minim(int x, int y) {
	if (x < y)
		return x;
	return y;
}