#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
#ifdef INFOARENA
#define ProblemName "barbar"
#endif
#define MCONCAT(A, B) A B
#ifdef ProblemName
#define InFile MCONCAT(ProblemName, ".in")
#define OuFile MCONCAT(ProblemName, ".out")
#else
#define InFile "in"
#define OuFile "out"
#endif
#define MAXN 1100
typedef pair<int, int> square;
#define mp make_pair
char M[MAXN][MAXN];
int R, C;
int prec[MAXN][MAXN];
int dst[MAXN][MAXN];
bool viz[MAXN][MAXN];
int entrance[2], outway[2];
queue<square> Q;
inline char isEmpty(int i, int j) {
return (M[i][j] != 'D' && M[i][j] != '*');
}
void BFSprec() {
memset(prec, 0, sizeof(prec));
memset(viz, 0, sizeof(viz));
for (int i = 0; i < R; ++i)
for (int j = 0; j < C; ++j)
if (M[i][j] == 'D') {
Q.push(make_pair(i, j));
viz[i][j] = 1;
}
while (!Q.empty()) {
pair<int, int> t = Q.front();
Q.pop();
for (int i = -1; i <= 1; ++i)
for (int j = -1; j <= 1; ++j) {
if ((i == 0 && j == 0) || i * j)
continue;
int x = t.first + i, y = t.second + j;
if (x < 0 || x >= R || y < 0 || y >= C)
continue;
if (!isEmpty(x, y))
continue;
if (viz[x][y])
continue;
prec[x][y] = prec[t.first][t.second] + 1;
viz[x][y] = 1;
Q.push(make_pair(x, y));
}
}
}
char DFS(int t1, int t2, int ans) {
viz[t1][t2] = 1;
if (t1 == outway[0] && t2 == outway[1])
return 1;
for (int i = -1; i <= 1; ++i)
for (int j = -1; j <= 1; ++j) {
if ((i == 0 && j == 0) || i * j)
continue;
int x = t1 + i, y = t2 + j;
if (x < 0 || x >= R || y < 0 || y >= C)
continue;
if (!isEmpty(x, y))
continue;
if (viz[x][y])
continue;
if (prec[x][y] < ans)
continue;
if (DFS(x, y, ans))
return 1;
}
return 0;
}
#define QELEM(x,y) mp(dst[x][y], mp(x, y))
int drum[] = { 0, 1, 0, -1, 1, 0, -1, 0 };
void printMat(int a[MAXN][MAXN]) {
for (int i = 0; i < R; ++i) {
for (int j = 0; j < C; ++j)
printf("%d ", dst[i][j]);
puts("");
}
}
int solve() {
BFSprec();
memset(dst, 0x3F, sizeof dst);
memset(viz, 0, sizeof viz);
priority_queue< pair<int, square> > Q;
dst[entrance[0]][entrance[1]] = prec[entrance[0]][entrance[1]];
Q.push(QELEM(entrance[0], entrance[1]));
while (!Q.empty()) {
auto it = Q.top(); Q.pop();
int ti = it.second.first, tj = it.second.second;
int tdst = it.first;
for (int di = 0; di < 4; ++di) {
int ni = ti + drum[di * 2], nj = tj + drum[di * 2 + 1];
if (ni < 0 || ni >= R || nj < 0 || nj >= C) continue;
if (!isEmpty(ni, nj)) continue;
int cand = min(dst[ti][tj], prec[ni][nj]);
if (cand >= dst[ni][nj]) continue;
if (viz[ni][nj]) continue;
dst[ni][nj] = cand;
if (ni == outway[0] && nj == outway[1]) return cand;
Q.push(QELEM(ni, nj));
viz[ni][nj] = true;
}
}
if (!viz[outway[0]][outway[1]]) return -1;
return dst[outway[0]][outway[1]];
}
void readInput() {
scanf("%d%d", &R, &C);
for (int i = 0; i < R; ++i)
for (int j = 0; j < C; ++j) {
scanf(" %c", &M[i][j]);
if (M[i][j] == 'I')
entrance[0] = i, entrance[1] = j;
else if (M[i][j] == 'O')
outway[0] = i, outway[1] = j;
}
}
int main() {
freopen(InFile, "r", stdin);
freopen(OuFile, "w", stdout);
readInput();
printf("%d\n", solve());
return 0;
}