Cod sursa(job #2923793)

Utilizator cezar_titianuTitianu Cezar cezar_titianu Data 19 septembrie 2022 10:55:14
Problema Barbar Scor 80
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.37 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>

#define MAXN 1005

#define viz(pos) vizvec[pos.x * nrn + pos.y]
#define viz2(x, y) vizvec[(x) * nrn + (y)]

struct coord {
	size_t x;
	size_t y;
};

struct dijnode {
	size_t x;
	size_t y;
	int dist;

	bool operator<(const dijnode &nr2) const {
		return dist < nr2.dist;
	}
};

struct node {
	bool wall;
	int dist;
};

node mat[MAXN][MAXN];

void initDist(const std::vector <coord> &initpos, const int &nrn, const int &nrm) {
	int dist = 0;
	int addcnt = initpos.size();
	std::vector <bool> vizvec(nrn * nrm);
	std::queue <coord> next;
	for(const coord &init : initpos) {
		viz(init) = true;
		next.push(init);
	}
	coord now;
	while(!next.empty()) {
		now = next.front();
		next.pop();
		mat[now.x][now.y].dist = dist;
		if(now.x > 0 && !viz2(now.x - 1, now.y)) {
			next.push({ now.x - 1, now.y});
			viz2(now.x - 1, now.y) = true;
		}
		if(now.x < nrn - 1 && !viz2(now.x + 1, now.y)) {
			next.push({ now.x + 1, now.y});
			viz2(now.x + 1, now.y) = true;
		}
		if(now.y > 0 && !viz2(now.x, now.y - 1)) {
			next.push({ now.x, now.y - 1});
			viz2(now.x, now.y - 1) = true;
		}
		if(now.y < nrm - 1 && !viz2(now.x, now.y + 1)) {
			next.push({ now.x, now.y + 1});
			viz2(now.x, now.y + 1) = true;
		}
		addcnt--;
		if(addcnt == 0) {
			dist++;
			addcnt = next.size();
		}
	}
}

int calcPath(const coord &init, const coord &stop, const int &nrn, const int &nrm) {
	std::vector <bool> vizvec(nrn * nrm);
	std::priority_queue <dijnode> next;
	next.push({ init.x, init.y, mat[init.x][init.y].dist});
	viz(init) = true;
	dijnode now;
	while(!next.empty()) {
		now = next.top();
		next.pop();
		if(now.x == stop.x && now.y == stop.y) {
			return now.dist;
		}
		if(now.x > 0 && !viz2(now.x - 1, now.y) && !mat[now.x - 1][now.y].wall) {
			next.push({ now.x - 1, now.y, std::min(now.dist, mat[now.x - 1][now.y].dist)});
			viz2(now.x - 1, now.y) = true;
		}
		if(now.x < nrn - 1 && !viz2(now.x + 1, now.y) && !mat[now.x + 1][now.y].wall) {
			next.push({ now.x + 1, now.y, std::min(now.dist, mat[now.x + 1][now.y].dist)});
			viz2(now.x + 1, now.y) = true;
		}
		if(now.y > 0 && !viz2(now.x, now.y - 1) && !mat[now.x][now.y - 1].wall) {
			next.push({ now.x, now.y - 1, std::min(now.dist, mat[now.x][now.y - 1].dist)});
			viz2(now.x, now.y - 1) = true;
		}
		if(now.y < nrm - 1 && !viz2(now.x, now.y + 1) && !mat[now.x][now.y + 1].wall) {
			next.push({ now.x, now.y + 1, std::min(now.dist, mat[now.x][now.y + 1].dist)});
			viz2(now.x, now.y + 1) = true;
		}
	}
	return -1;
}

int main () {
	std::ifstream fin("barbar.in");
	std::ofstream fout("barbar.out");
	int nrn, nrm;
	coord init, stop;
	std::vector <coord> dragons;
	char chr;
	fin >> nrn >> nrm;
	for(size_t index = 0; index < nrn; index++) {
		for(size_t index2 = 0; index2 < nrm; index2++) {
			fin >> chr;
			switch (chr) {
				case '.':
					mat[index][index2].wall = false;
					break;
				case 'I':
					mat[index][index2].wall = false;
					init = {index, index2};
					break;
				case 'O':
					mat[index][index2].wall = false;
					stop = {index, index2};
					break;
				case '*':
					mat[index][index2].wall = true;
					break;
				case 'D':
					mat[index][index2].wall = false;
					dragons.push_back({index, index2});
					break;
				default:
					std::cerr << "Unrecognised input character.\n";
					return 0;
			}
		}
	}
	initDist(dragons, nrn, nrm);
	fout << calcPath(init, stop, nrn, nrm);
	return 0;
}