#include <iostream>
#include <fstream>
#define MAX 1001
using namespace std;
char a[MAX][MAX];
bool seen[MAX][MAX];
short int lindir[] = {-1, 0, 1, 0}, coldir[] = {0, 1, 0, -1};
struct
{
int x;
int y;
}coada[MAX * MAX], dragoni[MAX * MAX];
bool verificare(int x, int y, int n, int m, int contor, int limita)
{
if(x >= 1 && x <= n && y >= 1 && y <= m && !seen[x][y] && a[x][y] != '*')
{
int i;
for(i = 1; i <= contor; i++)
if(abs(dragoni[i].x - x) + abs(dragoni[i].y - y) < limita)return false;
return true;
}
return false;
}
void clean(int n, int m)
{
int i, j;
for(i = 1; i <= n; i++)
for(j = 1; j <= m; j++)
seen[i][j] = 0;
}
bool lee(int n, int m, int limita, int pornireX, int pornireY, int exitX, int exitY, int contor)
{
int lin, col, i, st, dr;
st = dr = 1;
coada[st].x = pornireX;
coada[st].y = pornireY;
seen[pornireX][pornireY] = 1;
while(st <= dr)
{
for(i = 0; i <= 3; i++)
{
lin = coada[st].x + lindir[i];
col = coada[st].y + coldir[i];
if(verificare(lin, col, n, m, contor, limita))
{
dr++;
coada[dr].x = lin;
coada[dr].y = col;
seen[lin][col] = 1;
}
}
st++;
}
return seen[exitX][exitY];
}
int main()
{
int n, m, contor, i, j, pornireX, pornireY, exitX, exitY, st, dr, mij, sol;
ifstream fin("barbar.in");
ofstream fout("barbar.out");
fin >> n >> m;
contor = 0;
for(i = 1; i <= n; i++)
{
fin >> a[i];
for(j = m; j > 0; j--)
{
a[i][j] = a[i][j - 1];
if(a[i][j] == 'D')
{
contor++;
dragoni[contor].x = i;
dragoni[contor].y = j;
}
else if(a[i][j] == 'I')
{
pornireX = i;
pornireY = j;
}
else if(a[i][j] == 'O')
{
exitX = i;
exitY = j;
}
}
}
st = 1;
dr = n + m - 2;
sol = -1;
while(st <= dr)
{
mij = (st + dr) / 2;
clean(n, m);
if(lee(n, m, mij, pornireX, pornireY, exitX, exitY, contor))
{
sol = mij;
st = mij + 1;
}
else dr = mij - 1;
}
fout << sol;
return 0;
}