#include <iostream>
#include <stdio.h>
using namespace std;
#define MAXRC 1000
#define NRDIR 4
#define INF (MAXRC * MAXRC + 1)
int mat[MAXRC + 2][MAXRC + 2], minime[MAXRC + 2][MAXRC + 2], filled[MAXRC + 2][MAXRC + 2], q[MAXRC * MAXRC][2];///pentru ca imi permit si imi e lene sa fac coada de MAXRC * 2 si sa stau sa fac mod de fiecare data cu posibilitatea considerabil de mare de a gresi
int dirl[NRDIR] = {1, 0, -1, 0}, dirc[NRDIR] = {0, -1, 0, 1};
void fillminime(int l, int c, int cod){
int p, u, cu, i, lenght;
p = 0;
u = 1;
q[0][0] = l;
q[0][1] = c;
minime[l][c] = 0;
lenght = 1;
while(p < u){
cu = u;
while(p < cu){
for(i = 0; i < NRDIR; i++){
if((filled[q[p][0] + dirl[i]][q[p][1] + dirc[i]] == cod) && (lenght < minime[q[p][0] + dirl[i]][q[p][1] + dirc[i]])){
q[u][0] = q[p][0] + dirl[i];
q[u][1] = q[p][1] + dirc[i];
u++;
minime[q[p][0] + dirl[i]][q[p][1] + dirc[i]] = lenght;
filled[q[p][0] + dirl[i]][q[p][1] + dirc[i]] = cod + 1;
}
}
p++;
}
lenght++;
}
}
void fillcanmakeit(int& l, int& c, int& min){
int i;
filled[l][c] = 2;
for(i = 0; i < NRDIR; i++){
if((filled[l + dirl[i]][c + dirc[i]] == 1) && (min <= minime[l + dirl[i]][c + dirc[i]])){
l += dirl[i];
c += dirc[i];
fillcanmakeit(l, c, min);
l -= dirl[i];
c -= dirc[i];
}
}
}
void resetfilled(int n, int m){
int l, c;
for(l = 1; l <= n; l++){
for(c = 1; c <= m; c++){
if(filled[l][c] != 0){
filled[l][c] = 1;
}
}
}
}
int cautare(int n, int m, int startl, int startc, int finall, int finalc){
int min, max, mij, csl, csc;
min = 0;
max = n + m;///incercam asa:))
while((max - min) > 1){
mij = (max + min) / 2;
csc = startc;
csl = startl;
resetfilled(n, m);
fillcanmakeit(csc, csl, mij);
if(filled[finall][finalc] == 1){///daca nu am putut sa trec prin pozitia finala
max = mij;
}else{
min = mij;
}
}
return min;
}
int main()
{
FILE *fin, *fout;
int n, m, l, c, cod, startl, startc, finall, finalc;
fin = fopen("barbar.in", "r");
fscanf(fin, "%d%d", &n, &m);
for(l = 1; l <= n; l++){
mat[l][1] = fgetc(fin);
for(c = 1; c <= m; c++){
mat[l][c] = fgetc(fin);
if(mat[l][c] != '*'){
if(mat[l][c] == 'I'){
startl = l;
startc = c;
}else if(mat[l][c] == 'O'){
finall = l;
finalc = c;
}
filled[l][c] = 1;
minime[l][c] = INF;
}
}
}
fclose(fin);
cod = 1;
for(l = 1; l <= n; l++){
for(c = 1; c <= m; c++){
if(mat[l][c] == 'D'){
fillminime(l, c, cod);
cod++;
}
}
}
fout = fopen("barbar.out", "w");
fprintf(fout, "%d", cautare(n, m, startl, startc, finall, finalc));
fclose(fout);
return 0;
}