#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;
}