#include <iostream>
#include <fstream>
using namespace std;
void createMap(int, int[], int[], int, int, int[], int[], char**, int**);
void searchMin(int&, int, int, char**, int**, int, int, int, int, int, int);
int canCreatePath(int, int, char**, int**, int, int, int, int, int);
int main() {
ifstream f("barbar.in");
ofstream g("barbar.out");
int n, m;
f >> n >> m;
char **a = new char*[n];
int **b = new int*[n];
for (int i = 0; i < n; ++i) {
b[i] = new int[m];
a[i] = new char[m];
}
int dragonNumber = 0;
int dragonX[n * m];
int dragonY[n * m];
int stx, sty, finx, finy;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
b[i][j] = 0;
f >> a[i][j];
if (a[i][j] == 'D') {
dragonX[dragonNumber] = i;
dragonY[dragonNumber] = j;
dragonNumber ++;
} else if (a[i][j] == 'I') {
stx = i;
sty = j;
} else if (a[i][j] == 'O') {
finx = i;
finy = j;
}
}
}
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};
createMap(dragonNumber, dragonX, dragonY, n, m, dx, dy, a, b);
/*
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
cout << b[i][j] << " ";
}
cout << "\n";
}*/
int minimDistance = n * m + 2;
searchMin(minimDistance, n, m, a, b, 0, n * m, stx, sty, finx, finy);
if (minimDistance == n * m + 2) {
g << -1;
} else {g << minimDistance - 1;}
return 0;
}
void createMap(int dragonNumber, int dragonX[], int dragonY[], int n, int m, int dx[], int dy[], char **a, int**b) {
int coadaX[n * m];
int coadaY[n * m];
int st = 0;
int fin = 0;
for (int i = 0; i < dragonNumber; ++i) {
coadaX[i] = dragonX[i];
coadaY[i] = dragonY[i];
b[coadaX[i]][coadaY[i]] = 1;
fin ++;
}
fin --;
while (st <= fin) {
int currentX = coadaX[st];
int currentY = coadaY[st];
st ++;
for (int j = 0; j < 4; ++j) {
int xAux = currentX + dx[j];
int yAux = currentY + dy[j];
if ( 0 <= xAux && xAux < n && 0 <= yAux && yAux < m && a[xAux][yAux] != '*' && b[xAux][yAux] == 0 ) {
fin ++;
b[xAux][yAux] = b[currentX][currentY] + 1;
coadaX[fin] = xAux;
coadaY[fin] = yAux;
}
}
}
}
void searchMin(int &minimDistance, int n, int m, char **a, int **b, int st, int dr, int stx, int sty, int finx, int finy) {
if (st <= dr) {
if ( st == dr ) {
if (canCreatePath(n, m, a, b, st, stx, sty, finx, finy) == 1) {
if (minimDistance == n * m + 2) {
minimDistance = st;
} else {
minimDistance = max(st, minimDistance);
}
}
} else {
int mij = (st + dr) / 2;
if ( canCreatePath(n, m, a, b, mij, stx, sty, finx, finy) == 1 ) {
minimDistance = mij;
searchMin(minimDistance, n, m, a, b, mij + 1, dr, stx, sty, finx, finy);
} else {
searchMin(minimDistance, n, m, a, b, st, mij, stx, sty, finx, finy);
}
}
}
}
int canCreatePath(int n, int m, char **a, int **b, int dist, int stx, int sty, int finx, int finy) {
int st = 0;
int fin = 0;
int coadaX[n * m], coadaY[n * m];
coadaX[st] = stx;
coadaY[st] = sty;
bool canContinue = true;
int vis[n][m];
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
vis[i][j] = 0;
}
}
vis[stx][sty] = 1;
while (st <= fin && vis[finx][finy] == 0) {
int currentX = coadaX[st];
int currentY = coadaY[st];
st ++;
for (int i = 0; i < 4; ++i) {
int xAux = currentX + dx[i];
int yAux = currentY + dy[i];
if (0 <= xAux && xAux < n && 0 <= yAux && yAux < m && a[xAux][yAux] != '*' && vis[xAux][yAux] == 0 && b[xAux][yAux] >= dist) {
fin ++;
vis[xAux][yAux] = 1;
coadaX[fin] = xAux;
coadaY[fin] = yAux;
}
}
}
return (vis[finx][finy] != 0);
}