#include <fstream>
#include <queue>
using namespace std;
ifstream fin("barbar.in");
ofstream fout("barbar.out");
const int N = 1e3;
const int INIT = 1e9;
const int DIRS = 4;
char v[N+1][N+1];
int dragons[N+1][N+1];
int lee[N+1][N+1];
int dln[] = {-1,0,1,0};
int dcl[] = {0,-1,0,1};
void reset(int v[N+1][N+1], int nl, int nc){
for (int i = 1; i<=nl; i++)
for (int j = 1; j<=nc; j++)
v[i][j]=INIT;
}
void golee(int lee[N+1][N+1], int ln, int cl, int nl, int nc, int k, bool avoid){
queue<pair<int,int>> q;
lee[ln][cl] = 0;
q.push({ln,cl});
while(!q.empty()){
ln = q.front().first;
cl = q.front().second;
q.pop();
if (lee[ln][cl]<k)
for (int i = 0; i<4; i++){
int fln = ln+dln[i];
int fcl = cl+dcl[i];
if (fln>0 && fln<=nl && fcl>0 && fcl<=nc && v[fln][fcl]!='*' &&
lee[fln][fcl]>lee[ln][cl]+1 && (avoid == 0 || dragons[fln][fcl]==INIT)){
lee[fln][fcl]=lee[ln][cl]+1;
q.push({fln,fcl});
}
}
}
}
bool sePoate(int k, int iln, int icl, int oln, int ocl, int nl, int nc){
reset(dragons, nl, nc);
reset(lee, nl, nc);
for (int i = 1; i<=nl; i++){
for (int j = 1; j<=nc; j++){
if (v[i][j]=='D'){
golee(dragons,i,j,nl,nc,k,0);
}
}
}
golee(lee,iln,icl,nl,nc,1e9,1);
return (lee[oln][ocl]!=INIT);
}
int cb(int iln, int icl, int oln, int ocl, int nl, int nc){
int st = 0, dr=INIT, rez = st-1;
while (st<=dr){
int m = (st+dr)/2;
if (sePoate(m,iln,icl,oln,ocl,nl,nc)){
rez = m;
st = m+1;
}
else{
dr = m-1;
}
}
return rez;
}
int main(){
int nl, nc;
fin>>nl>>nc;
int iln=0,icl=0,oln=0,ocl=0;
for (int i = 1; i<=nl; i++){
for (int j = 1; j<=nc; j++){
fin>>v[i][j];
if (v[i][j]=='I'){
iln = i;
icl = j;
}
if (v[i][j]=='O'){
oln=i;
ocl=j;
}
}
}
int sol = cb(iln,icl,oln,ocl,nl,nc)+1;
if (sol == 0)
fout<<-1;
else
fout<<sol;
}