#include <fstream>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
ifstream cin("barbar.in");
ofstream cout("barbar.out");
const int INF = 2e9;
const int MAX = 1005;
int di[4] = {0, 0, 1, -1};
int dj[4] = {1, -1, 0, 0};
vector < vector < bool > > walled(MAX, vector < bool > (MAX));
vector < vector < int > > dist_drag(MAX, vector < int > (MAX, INF));
vector < vector < bool > > used(MAX, vector < bool > (MAX));
bool is_good(int i, int j, int n, int m) {
return i >= 1 and j >= 1 and i <= n and j <= m;
}
void read(int n, int m, pair < int, int > &me, pair < int, int > &dest, queue < pair < int, int > > &drags) {
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= m; j ++) {
char c;
cin >> c;
if (c == 'I') {
me = {i, j};
}
else if (c == 'O') {
dest = {i, j};
}
else if (c == 'D') {
drags.push({i, j});
}
else if (c == '*') {
walled[i][j] = true;
}
}
}
}
void complete (pair < int, int > dragon, int n, int m) {
queue < pair < int, int > > q;
dist_drag [dragon.first][dragon.second] = 0;
walled[dragon.first][dragon.second] = true;
q.push(dragon);
while (!q.empty()) {
auto cur = q.front();
q.pop();
for (int i = 0; i < 4; i ++) {
int row = cur.first + di[i];
int col = cur.second + dj[i];
if (!is_good(row, col, n, m)) continue;
if (walled[row][col]) continue;
if (dist_drag[row][col] <= dist_drag[cur.first][cur.second] + 1) continue;
dist_drag[row][col] = dist_drag[cur.first][cur.second] + 1;
q.push({row, col});
}
}
}
void reset(vector < vector < bool > > &used, int n, int m) {
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= m; j ++) {
used[i][j] = false;
}
}
}
bool found_path(int min_dist, pair < int, int > me, pair < int, int > dest, int n, int m) {
reset(used, n, m);
queue < pair < int, int > > q;
if (dist_drag[me.first][me.second] >= min_dist) {
q.push(me);
used[me.first][me.second] = true;
}
while (!q.empty()) {
auto cur = q.front();
q.pop();
for (int i = 0; i < 4; i ++) {
int row = cur.first + di[i];
int col = cur.second + dj[i];
if (used[row][col])continue;
used[row][col] = true;
if (!is_good(row, col, n, m)) continue;
if (walled[row][col]) continue;
if (dist_drag[row][col] < min_dist) continue;
if (dest == make_pair(row, col)) return true;
q.push({row, col});
}
}
return false;
}
int main(int argc, char const *argv[]) {
int n, m;
cin >> n >> m;
queue < pair < int, int > > drags;
pair < int, int > me;
pair < int, int > dest;
read(n , m, me, dest, drags);
while (!drags.empty()) {
complete(drags.front(), n, m);
drags.pop();
}
int sol = -1;
int ans = 0;
for (int bit = log2(n + m + 1); bit > 0; bit --) {
if ((1 << bit) > n + m + 1) continue;
if (found_path(ans + (1 << bit), me, dest, n, m)) {
ans += (1 << bit);
sol = ans;
}
}
cout << sol << '\n';
return 0;
}