#include <bits/stdc++.h>
using namespace std;
template <typename T> ostream& operator<<(ostream &os, const vector<T> &v) { os << '{'; string sep; for (const auto &x : v) os << sep << x, sep = ", "; return os << '}'; }
template <typename A, typename B> ostream& operator<<(ostream &os, const pair<A, B> &p) { return os << '(' << p.first << ", " << p.second << ')'; }
using i64 = long long int;
const int INF = INT_MAX, MOD = 1e9 + 7;
const long long LINF = LLONG_MAX;
const double EPS = 1e-9, PI = acos(-1);
const int dx[] = {0, 0, 0, -1, 1, -1, 1, 1, -1};
const int dy[] = {0, -1, 1, 0, 0, -1, 1, -1, 1};
struct Lee {
vector<string> adj;
vector<vector<bool>> marked;
vector<vector<int>> closest_dragon;
pair<int, int> in, out;
int n, m;
Lee(int _n = 0, int _m = 0) {
init(_n, _m);
}
void init(int _n, int _m) {
n = _n; m = _m;
marked.resize(n);
closest_dragon.resize(n);
for (int i = 0; i < n; i++) {
marked[i].resize(m, false);
closest_dragon[i].resize(m, INF);
}
}
void dragon_distances() {
queue<pair<int, int>> q;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
if (adj[i][j] == 'D') {
q.emplace(i, j);
closest_dragon[i][j] = 0;
}
}
while (not q.empty()) {
pair<int, int> now = q.front();
q.pop();
for (int i = 1; i <= 4; i++) {
pair<int, int> next = {now.first + dx[i], now.second + dy[i]};
if (next.first < 0 or next.second < 0 or next.first >= n or next.second >= m) continue;
if (adj[next.first][next.second] == '*') continue;
if (closest_dragon[next.first][next.second] <= closest_dragon[now.first][now.second] + 1) continue;
closest_dragon[next.first][next.second] = closest_dragon[now.first][now.second] + 1;
q.push(next);
}
}
}
bool LeeBFS(int value) {
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
marked[i][j] = false;
queue<pair<int, int>> q;
q.push(in);
marked[in.first][in.second] = true;
while (not q.empty()) {
pair<int, int> now = q.front();
q.pop();
for (int i = 1; i <= 4; i++) {
pair<int, int> next = {now.first + dx[i], now.second + dy[i]};
if (next.first < 0 or next.second < 0 or next.first >= n or next.second >= m) continue;
if (adj[next.first][next.second] == '*' or adj[next.first][next.second] == 'D') continue;
if (closest_dragon[next.first][next.second] < value) continue;
if (marked[next.first][next.second]) continue;
marked[next.first][next.second] = true;
q.push(next);
}
}
return marked[out.first][out.second];
}
int binary_search_distance(int lo, int hi) {
int ans = -1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (LeeBFS(mid)) {
ans = mid;
lo = mid + 1;
} else
hi = mid - 1;
}
return ans;
}
};
int main() {
ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
/// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
ifstream cin("barbar.in");
ofstream cout("barbar.out");
int N, M; cin >> N >> M;
Lee lee(N, M);
string row;
for (int i = 0; i < N; i++) {
cin >> row;
lee.adj.push_back(row);
for (int j = 0; j < M; j++) {
if (row[j] == 'I')
lee.in = {i, j};
else if (row[j] == 'O')
lee.out = {i, j};
}
}
lee.dragon_distances();
int ans = lee.binary_search_distance(1, lee.closest_dragon[lee.in.first][lee.in.second]);
cout << ans;
return 0;
}