#include <bits/stdc++.h>
using namespace std;
ifstream f("barbar.in");
ofstream g("barbar.out");
const int N = 1024;
int n, m, xs, ys, xf, yf, answer = 0, viz[N][N], d[N][N], valid(int, int);
int dx[] = {0, 0, -1, 1};
int dy[] = {1, -1, 0, 0};
char c;
void Search(int, int, int);
queue <pair<int, int>> q;
int main()
{
f >> n >> m;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
{
f >> c;
if(c == 'I')
xs = i, ys = j;
else if(c == 'O')
xf = i, yf = j;
else if(c == '*')
d[i][j] = -1;
else if(c == 'D')
d[i][j] = 1, q.push({i, j});
}
while(!q.empty())
{
int x, y;
tie(x, y) = q.front();
q.pop();
for(int i = 0; i < 4; i++)
{
int new_x = x + dx[i], new_y = y + dy[i];
if(valid(new_x, new_y) && (d[new_x][new_y] == 0 || d[new_x][new_y] > d[x][y] + 1))
{
d[new_x][new_y] = d[x][y] + 1;
q.push({new_x, new_y});
}
}
}
Search(xs, ys, d[xs][ys]);
g << answer - 1;
return 0;
}
int valid(int x, int y)
{
if(x < 1 || x > n || y < 1 || y > m || d[x][y] == -1)
return 0;
return 1;
}
void Search(int x, int y, int actualmax)
{
if(x == xf && y == yf)
{
answer = max(answer, actualmax);
return;
}
viz[x][y] = 1;
vector<tuple<int, int, int>> v;
for(int i = 0; i < 4; i++)
{
int new_x = x + dx[i], new_y = y + dy[i];
if(valid(new_x, new_y) && !viz[new_x][new_y] )
v.push_back(make_tuple(d[new_x][new_y], new_x, new_y));
}
sort(v.begin(), v.end());
for(int i = v.size() - 1; i >= 0; i--)
{
int new_x, new_y, dist;
tie(dist, new_x, new_y) = v[i];
Search(new_x, new_y, min(dist, actualmax));
}
}