#include <stdio.h>
#include <assert.h>
#define Smerenie 1000000
#define MAX_Q 131071
#define Nadejde 1000
#define MAX_DIR 4
#define NIL -1
const int delta[MAX_DIR][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
typedef struct {
int l, c;
} pair;
int N, M, ss;
int qhead, qtail;
pair start, finish;
pair queue[MAX_Q + 1];
pair stack[Smerenie + 1];
int d[Nadejde + 2][Nadejde + 2];
char s[Nadejde + 2][Nadejde + 2];
char seen[Nadejde + 2][Nadejde + 2];
/** Bordeaza matricea. **/
void overFlow(int n, int m) {
int i, j;
for (i = 0; i <= n; i++) {
d[i][0] = d[i][m] = NIL;
}
for (j = 0; j <= m; j++) {
d[0][j] = d[n][j] = NIL;
}
}
/** Construieste perechea (l, c). **/
pair make(int l, int c) {
pair tmp;
tmp.l = l;
tmp.c = c;
return tmp;
}
/** Pune in coada (l, c). **/
void enqueue(int l, int c, int dist) {
queue[qtail] = make(l, c);
d[l][c] = dist;
qtail = (qtail + 1) & MAX_Q;
}
/** Ia urmatorul element din coada. **/
void dequeue(int *l, int *c, int *dist) {
(*l) = queue[qhead].l;
(*c) = queue[qhead].c;
(*dist) = d[(*l)][(*c)] + 1;
qhead = (qhead + 1) & MAX_Q;
}
/** Determina pentru fiecare celula (l, c) distanta pana la cel mai apropiat dragon. **/
void init() {
int i, l, c, l0, c0, dist;
do {
dequeue(&l, &c, &dist);
for (i = 0; i < MAX_DIR; i++) {
l0 = l + delta[i][0];
c0 = c + delta[i][1];
if (!d[l0][c0]) {
enqueue(l0, c0, dist);
}
}
} while (qhead != qtail);
}
void refresh() {
int i, j;
for (i = 1; i <= N; i++) {
for (j = 1; j <= M; j++) {
seen[i][j] = 0;
}
}
}
void push(pair u) {
stack[ss++] = u;
seen[u.l][u.c] = 1;
}
void pop(pair *u) {
(*u) = stack[--ss];
}
int fire(int limit) {
int i;
pair next, node;
refresh();
push(start);
while (ss) {
pop(&node);
for (i = 0; i < MAX_DIR; i++) {
next = make(node.l + delta[i][0], node.c + delta[i][1]);
if ((!seen[next.l][next.c]) && (d[next.l][next.c] > limit)) {
push(next);
}
}
}
return seen[finish.l][finish.c];
}
int bSearch(int lo, int hi) {
while (hi - lo > 1) {
int mid = (lo + hi) >> 1;
if (fire(mid)) {
lo = mid;
} else {
hi = mid;
}
}
//fprintf(stderr, "%d %d\n", lo, hi);
if (lo == 0) assert(0);
return lo == 0 ? NIL : lo;
}
int main(void) {
int i, j;
FILE *f = fopen("barbar.in", "r");
/* Citirea datelor. */
fscanf(f, "%d %d", &N, &M);
for (i = 1; i <= N; i++) {
fscanf(f, "%s", s[i] + 1);
for (j = 1; j <= M; j++) {
if (s[i][j] == 'I') {
start = make(i, j);
} else if (s[i][j] == 'O') {
finish = make(i, j);
} else if (s[i][j] == 'D') {
enqueue(i, j, 1);
} else if (s[i][j] == '*') {
d[i][j] = NIL;
}
}
}
fclose(f);
/* Precalculare. */
overFlow(N + 1, M + 1);
init();
/* Calcularea solutiei si afisarea ei. */
freopen("barbar.out", "w", stdout);
fprintf(stdout, "%d\n", bSearch(0, d[start.l][start.c]));
fclose(stdout);
/// Multumim Doamne!
puts("Doamne ajuta!");
return 0;
}