#include <iostream>
#include <fstream>
#include <queue>
using namespace std;
ifstream fin("barbar.in");
ofstream fout("barbar.out");
int const INF=1<<30;
int const di[]={-1,0,1,0};
int const dj[]={0,1,0,-1};
int dist[1001][1001],drag[1001][1001];
char viz[1001][1001];
queue<pair<int,int> >q;
int n,m,xx,yy,xf,yf;
int pos(int a,int b)
{
if((a<=n && a>0) && (b>0 && b<=m))return 1;
return 0;
}
void bfs()
{
while(!q.empty())
{
int xi=q.front().first;
int yi=q.front().second;
q.pop();
for(int k=0;k<4;k++)
{
int a=xi+di[k];
int b=yi+dj[k];
if(pos(a,b) && drag[a][b]>drag[xi][yi]+1 && viz[a][b]!='*')
{
q.push({a,b});
drag[a][b]=drag[xi][yi]+1;
}
}
}
}
int verif(int mij,int xx,int yy,int xf,int yf)
{
if(drag[xx][yy] < mij)
return 0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
dist[i][j]=INF;
q.push({xx,yy});
dist[xx][yy]=0;
while(!q.empty())
{
int xi=q.front().first;
int yi=q.front().second;
q.pop();
for(int k=0;k<4;k++)
{
int a=xi+di[k];
int b=yi+dj[k];
if(pos(a,b) && viz[a][b]!='*' && drag[a][b]>=mij && dist[xi][yi]+1<dist[a][b])
{
q.push({a,b});
dist[a][b]=dist[xi][yi]+1;
}
}
}
if(dist[xf][yf]!=INF)
return 1;
else
return 0;
}
int cautare_binara(int st,int dr)
{
while(st<=dr)
{
int mij=(st+dr)/2;
if(verif(mij,xx,yy,xf,yf) && !verif(mij+1,xx,yy,xf,yf)) return mij;
else
if(verif(mij,xx,yy,xf,yf) && verif(mij-1,xx,yy,xf,yf)) st=mij-1;
else
dr=mij+1;
}
}
int main()
{
fin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
drag[i][j]=INF;
int i,j;
char p;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
fin>>viz[i][j];
char p=viz[i][j];
if(p=='I')
{
xx=i;yy=j;
}
else
if(p=='D')
{
q.push({i,j});
drag[i][j]=0;
}
else
if(p=='O')
{
xf=i;yf=j;
}
}
bfs();
fout<<cautare_binara(0,max(n,m));
return 0;
}