/*
#include <iostream>
#include <fstream>
#include <queue>
#define pii pair <int, int>
#define LIBER 0
#define PERETE 1
#define DRAGON 2
using namespace std;
ifstream fin("barbar.in");
ofstream fout("barbar.out");
const int N = 1000;
int original[N + 1][N + 1], harta[N + 1][N + 1], n, m;
bool reach[N + 1][N + 1];
/// ordine N, E, S, V:
int diri[] = {-1, 0, 1, 0};
int dirj[] = {0, 1, 0, -1};
void clear_harta(){
for(int i = 1; i <= N; i++)
for(int j = 1; j <= N; j++)
reach[i][j] = harta[i][j] = 0;
}
bool in_bounds(int i, int j){
return (1 <= i && i <= n && 1 <= j && j <= m);
}
void my_fill(pii nod){
reach[nod.first][nod.second] = true;
for(int dir = 0; dir < 4; dir++){
if(!reach[nod.first + diri[dir]][nod.second + dirj[dir]] && harta[nod.first + diri[dir]][nod.second + dirj[dir]] == LIBER && in_bounds(nod.first + diri[dir], nod.second + dirj[dir]))
my_fill({nod.first + diri[dir] ,nod.second + dirj[dir]});
}
}
int main(){
pii intrare, iesire;
fin >> n >> m;
char ch;
fin.get(ch); /// '\n'
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
fin.get(ch);
if(ch == 'I') intrare = {i, j};
if(ch == 'O') iesire = {i, j};
if(ch == 'D') original[i][j] = DRAGON;
if(ch == '*') original[i][j] = PERETE;
}
fin.get(ch); /// '\n'
}
int st = 0, dr = N, ans = -1;
while(st <= dr){
clear_harta();
int dist = (st + dr) / 2;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
harta[i][j] = original[i][j];
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(original[i][j] == DRAGON){
for(int dir = 0; dir < 4; dir++){
int x = i, y = j;
for(int k = 0; k < dist; k++){
x += diri[dir];
y += dirj[dir];
if(in_bounds(x, y) && original[x][y] == LIBER) harta[x][y] = PERETE;
else break;
}
}
}
}
}
my_fill(intrare);
if(reach[iesire.first][iesire.second]) ans = dist, st = dist + 1;
else dr = dist - 1;
}
if(ans != -1) ans++;
fout << ans;
return 0;
}
**/
// eu iau 50p si n am chef de debug, scz
#include <stdio.h>
#include <string.h>
#define NMAX 2000
typedef struct
{
int x,y;
} coord;
int n,m;
int xi,yi,xf,yf;
int dx[]={0,-1,0,1,0},dy[]={0,0,1,0,-1};
char s[NMAX+1][NMAX+1];
int d[NMAX+1][NMAX+1];
coord coada[NMAX*NMAX+1];
char viz[NMAX+1][NMAX+1];
int plee(int dist)
{
int p=0,q=0,i,xx,yy;
memset(viz,0,sizeof(viz));
coada[0].x=xi;
coada[0].y=yi;
viz[xi][yi]=1;
while (p<=q)
{
xx=coada[p].x;
yy=coada[p].y;
for (i=1;i<=4;i++)
if (xx+dx[i]>=0 && yy+dy[i]>=0)
if (d[xx+dx[i]][yy+dy[i]]>=dist && s[xx+dx[i]][yy+dy[i]]!='*' && !viz[xx+dx[i]][yy+dy[i]])
{
q++;
coada[q].x=xx+dx[i];
coada[q].y=yy+dy[i];
viz[xx+dx[i]][yy+dy[i]]=1;
if (xx+dx[i]==xf && yy+dy[i]==yf) return 1;
}
p++;
}
return 0;
}
int posiesit()
{
int p=0,q=0,i,xx,yy;
memset(viz,0,sizeof(viz));
coada[0].x=xi;
coada[0].y=yi;
viz[xi][yi]=1;
while (p<=q)
{
xx=coada[p].x;
yy=coada[p].y;
for (i=1;i<=4;i++)
if (xx+dx[i]>=0 && yy+dy[i]>=0 && xx+dx[i]<n && yy+dy[i]<m)
if (s[xx+dx[i]][yy+dy[i]]!='*' && !viz[xx+dx[i]][yy+dy[i]])
{
q++;
coada[q].x=xx+dx[i];
coada[q].y=yy+dy[i];
viz[xx+dx[i]][yy+dy[i]]=1;
if (xx+dx[i]==xf && yy+dy[i]==yf) return 1;
}
p++;
}
return 0;
}
int main()
{
int i,j,q=-1,xx,yy,p;
freopen("barbar.in","r",stdin);
freopen("barbar.out","w",stdout);
scanf("%d %d",&n,&m);
gets(s[0]);
for (i=0;i<n;i++)
gets(s[i]);
for (i=0;i<=n;i++)
for (j=0;j<=m;j++) d[i][j]=32000;
for (i=0;i<=m;i++) d[n][i]=32001;
for (j=0;j<=n;j++) d[j][m]=32001;
for (i=0;i<n;i++)
for (j=0;j<m;j++)
{
if (s[i][j]=='I') xi=i, yi=j;
if (s[i][j]=='D') coada[++q].x=i, coada[q].y=j, d[i][j]=0;
if (s[i][j]=='O') xf=i, yf=j;
}
p=0;
while (p<=q)
{
xx=coada[p].x;
yy=coada[p].y;
for (i=1;i<=4;i++)
if (xx+dx[i]>=0 && yy+dy[i]>=0)
if (d[xx+dx[i]][yy+dy[i]]==32000 && s[xx+dx[i]][yy+dy[i]]!='*')
{
q++;
coada[q].x=xx+dx[i];
coada[q].y=yy+dy[i];
d[xx+dx[i]][yy+dy[i]]=d[xx][yy]+1;
}
p++;
}
int dmax=d[xi][yi];
long step,dist=0;
for (step=1; step<=dmax ; step<<=1);
step<<=1;
if (!posiesit()) printf("-1\n");
else
{
for ( ; step>0; step>>=1)
if (dist+step<=dmax)
if (plee(dist+step)) dist+=step;
printf("%d\n",dist);
}
fclose(stdin);
fclose(stdout);
return 0;
}