#include<cstdio>
#include<cstring>
struct punct{int x,y;};
const int NMAX=1000,INF=NMAX*NMAX+1;
const bool DEBUG=false;
char v[NMAX+2][NMAX+2];
int d[NMAX+1][NMAX+1];
bool viz[NMAX+2][NMAX+2];
/// Sol: Creez o matrice in care tin d[i][j]= distanta minima de la (i,j) la un dragon(O(N*M)),
/// iar apoi caut binar distanta minima fata de un dragon si simulez(O(N*M*log(N))).
/// O(N*M+N*M*log(N))=O(N*M*log(N))
int linie[]= {0,1,0,-1};
int coloana[]={1,0,-1,0};
void fill(int l,int c,int val)
{
if(v[l][c]==0 || v[l][c]!='.' || d[l][c]<val)
return;
d[l][c]=val;
for(int i=0;i<4;i++)
fill(l+linie[i],c+coloana[i],val+1);
}
void Dragon(int l,int c,int val)
{
for(int i=0;i<4;i++)
fill(l+linie[i],c+coloana[i],val+1);
}
void Calculeaza_distantele(int n,int m)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(v[i][j]=='D')
Dragon(i,j,0);
}
void fill1(int l,int c,int val)
{
if(v[l][c]==0 || v[l][c]!='.' || d[l][c]<val || viz[l][c])
return;
viz[l][c]=true;
for(int i=0;i<4;i++)
fill1(l+linie[i],c+coloana[i],val);
}
bool Se_poate(int dist,punct in,punct sf)
{
memset(viz,0,sizeof viz);
for(int i=0;i<4;i++)
fill1(in.x+linie[i],in.y+coloana[i],dist);
for(int i=0;i<4;i++)
if(viz[sf.x+linie[i]][sf.y+coloana[i]])
return true;
return false;
}
int main()
{
FILE *in=fopen("barbar.in","r");
int n,m;
fscanf(in,"%d %d ",&n,&m);
punct inc,sf;
for(int i=1;i<=n;i++)
{
fscanf(in,"%s ",v[i]+1);
for(int j=1;j<=m;j++)
{
if(v[i][j]=='I')
inc.x=i,inc.y=j;
if(v[i][j]=='O')
sf.x=i,sf.y=j;
d[i][j]=INF;
}
}
fclose(in);
//Bordare - Nu e nevoie matricea e deja initializata cu 0
Calculeaza_distantele(n,m);
FILE *out=fopen("barbar.out","w");
if(DEBUG)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
fprintf(out,"%d ",d[i][j]);
}
fprintf(out,"\n");
}
}
int st=0,dr=n>m?n:m;
while(st<=dr)
{
int mij=(st+dr)/2;
if(Se_poate(mij,inc,sf))
st=mij+1;
else
dr=mij-1;
if(DEBUG)
{
fprintf(out,"%d\n",mij);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
fprintf(out,"%d ",viz[i][j]);
fprintf(out,"\n");
}
fprintf(out,"\n");
}
}
fprintf(out,"%d\n",dr);
fclose(out);
return 0;
}