Pagini recente » Cod sursa (job #101902) | Cod sursa (job #2589859) | Cod sursa (job #1191342) | Cod sursa (job #517446) | Cod sursa (job #2812905)
#include <fstream>
#include <queue>
#include <bitset>
///https://www.infoarena.ro/job_detail/2812738
using namespace std;
ifstream cin("barbar.in");
ofstream cout("barbar.out");
const int DIM = 1005;
int n, m;
int dist[DIM][DIM];
bitset<1> wall[DIM][DIM];
bitset<1> visited[DIM][DIM];
bitset<1> dragon[DIM][DIM];
struct Cell {
int x,y;
};
queue<Cell> q;
Cell start, finish;
bool isEqual( Cell a, Cell b)
{
return a.x == b.x and a.y == b.y;
}
bool isInside(Cell a)
{
return ( a.x >= 1 && a.x <= n && a.y >= 1 && a.y <= m );
}
bool isWall(Cell a)
{
return ( wall[a.x][a.y] == 1) ;
}
bool isDragon(Cell a)
{
return ( dragon[a.x][a.y] == 1) ;
}
bool isVisited(Cell a)
{
return ( visited[a.x][a.y] == 1) ;
}
/// cell valid = inside & not wall & not visited
bool isValid(Cell a) {
return (isInside(a) && !isWall(a) && !isVisited(a) and dist[a.x][a.y] < 0 && !isDragon(a));
}
bool isValidAndSafer(Cell a, int minDistanceDragon) {
return (isInside(a) && !isWall(a) && !isVisited(a) && !isDragon(a) && dist[a.x][a.y] >= minDistanceDragon);
}
/// calculate distance matrix
/// based on start cell from queue
void Lee_DragonDanger() {
const int dx[] = {-1, 0, 1, 0};
const int dy[] = { 0, 1, 0, -1};
while(!q.empty()) {
Cell a = q.front();
q.pop();
for(int dir = 0; dir < 4; dir++) {
Cell neighbor = {a.x + dx[dir], a.y + dy[dir]};
if(isValid(neighbor)) {
dist[neighbor.x][neighbor.y] = dist[a.x][a.y] + 1;
visited[neighbor.x][neighbor.y] = 1;
q.push(neighbor);
}
}
}
}
/// returns
/// true if there is a path having each point dist > minDist
/// false there is no path
bool Lee_PrisonerEscape(int minDragonDistance) {
const int dx[] = {-1, 0, 1, 0};
const int dy[] = { 0, 1, 0, -1};
/// check distance from the starting point !!!
if(dist[start.x][start.y] < minDragonDistance) {
return false;
}
while(!q.empty()) {
q.pop();
}
q.push(start);
///reset visited
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
visited[i][j] = 0;
}
}
/// prepare Lee
visited[start.x][start.y] = 1;
while(!q.empty()) {
Cell a = q.front();
q.pop();
/// we got a solution !!!!!
if( isEqual(a,finish)) {
return true;
}
for(int dir = 0; dir < 4; dir++) {
Cell neighbor = {a.x + dx[dir], a.y + dy[dir]};
if(isValidAndSafer(neighbor, minDragonDistance)) {
visited[neighbor.x][neighbor.y] = 1;
q.push(neighbor);
}
}
}
return false;
}
/// input
/// . celula libera
/// * perete
/// D dragon
/// I punctul de plecare al lui Paftenie
/// O iesirea din temnita
int main() {
/// reading input
string s;
cin >> n >> m;
for(int i = 1; i <= n; i++) {
cin >> s;
s = " " + s;
for(int j = 1; j <= m; j++) {
dist[i][j] = -1;
if(s[j] == 'I') {
start = {i, j};
}
else if(s[j] == 'O') {
finish = {i, j};
}
else if(s[j] == 'D') {
dragon[i][j] =1;
dist[i][j] = 0;
visited[i][j] =1;
q.push({i, j});
}
}
}
/// fill matrix of dragon danger
Lee_DragonDanger();
// for(int i = 1 ;i <=n;i++)
// {
// for(int j = 1 ;j <=m;j++)
// {
// cout << dist[i][j]<< " ";
// }
// cout << "\n";
// }
/// binary search a path having a min distance as big as possible
int st = 1, dr = n * m, sol = -1;
while(st <= dr){
int mij = (st + dr) / 2;
if(Lee_PrisonerEscape(mij)) {
sol = mij; st = mij + 1;
}
else {
dr = mij - 1;
}
}
cout << sol << "\n";
return 0;
}