#include<fstream>
#include<queue>
#include<cstring>
using namespace std;
#define INF 0x3f3f3f3f
ifstream fin("barbar.in");
ofstream fout("barbar.out");
struct cel
{
int l,c;
} x,y;
queue <cel> q;
char A[1005][1005];
int dx[4]={-1,0,1},dy[4]={0,1,0,-1};
int n,m,xi,yi,xo,yo,st,dr,mij,Max,D[1005][1005],N[1005][1005];
void citire()
{
int i,j;
fin>>n>>m;
fin.get();
for (i=1;i<=n;++i)
{
for (j=1;j<=m;++j)
{
D[i][j]=INF;
fin.get(A[i][j]);
if (A[i][j]=='I') xi=i, yi=j;
if (A[i][j]=='O') xo=i, yo=j;
if (A[i][j]=='D')
{
D[i][j]=0;
x.l=i, x.c=j;
q.push(x);
}
}
fin.get();
}
for (i=0;i<=n+1;++i)
A[i][0]=A[i][m+1]='*';
for (i=1;i<=m;++i)
A[0][i]=A[n+1][i]='*';
}
void lee()
{
int i,lv,cv;
while (!q.empty())
{
x=q.front(); q.pop();
for (i=0;i<4;++i)
{
lv=x.l+dx[i], cv=x.c+dy[i];
if (A[lv][cv]!='*' && D[lv][cv]>D[x.l][x.c]+1)
{
D[lv][cv]=D[x.l][x.c]+1;
Max=max(Max,D[lv][cv]);
y.l=lv, y.c=cv;
q.push(y);
}
}
}
}
int fill(int a)
{
int i,lv,cv;
memset(N,0,sizeof(N));
N[xi][yi]=1;
x.l=xi, x.c=yi;
q.push(x);
while (!q.empty())
{
x=q.front(); q.pop();
for (i=0;i<4;++i)
{
lv=x.l+dx[i], cv=x.c+dy[i];
if (D[lv][cv]>=a && A[lv][cv]!='*' && !N[lv][cv])
{
N[lv][cv]=1;
y.l=lv, y.c=cv;
q.push(y);
}
}
}
return N[xo][yo];
}
int main()
{
citire();
lee();
st=0, dr=Max;
while (st<=dr)
{
mij=(st+dr)>>1;
if (fill(mij))
st=mij+1;
else
dr=mij-1;
}
if (dr>Max || dr<0)
fout<<"-1\n";
else
fout<<dr<<"\n";
return 0;
}