#include <fstream>
#include <utility>
#include <queue>
using namespace std;
struct comanda{
pair<int, int> p;
int val; };
constexpr bool operator<(const comanda& lhs, const comanda& rhs){
return lhs.val < rhs.val; }
template <typename T>
class mat{
T* buf;
public:
const int n, m;
constexpr mat(const int N, const int M):
buf(new T[N*M]), n(N), m(M){}
~mat(){
delete[] buf; }
constexpr T& la(const int x, const int y){
return buf[x*m + y]; }
constexpr T& operator[](const pair<int, int>& p){
return la(p.first, p.second); }
constexpr T& operator[](const comanda& c){
return (*this)[c.p]; }
void edge(const int val){
for(int i = 0; i < n; ++i){
la(i, 0) = val;
la(i, m-1) = val; }
for(int i = 0; i < m; ++i){
la(0, i) = val;
la(n-1, i) = val; } } };
constexpr int gol = -3, blocat = -4, dl[] = {0, 1, 0, -1}, dc[] = {1, 0, -1, 0},
inf = 1000001;
void citeste_mat(ifstream& f, const int n, const int m, mat<int>& distdrag, mat<int>& distpaft, queue<pair<int, int> >& dragoni,
pair<int, int>& paftenie, pair<int, int>& iesire){
char* buf = new char[m+1];
for(int i = 1; i <= n; ++i){
f.read(buf, m+1);
for(int j = 1; j <= m; ++j){
switch(buf[j]){
case '.':
distdrag.la(i, j) = gol;
distpaft.la(i, j) = -inf;
break;
case '*':
distdrag.la(i, j) = blocat;
distpaft.la(i, j) = blocat;
break;
case 'D':
distdrag.la(i, j) = 0;
distpaft.la(i, j) = -inf;
dragoni.emplace(i, j);
break;
case 'I':
distdrag.la(i, j) = gol;
distpaft.la(i, j) = -inf;
paftenie.first = i;
paftenie.second = j;
break;
case 'O':
distdrag.la(i, j) = gol;
distpaft.la(i, j) = -inf;
iesire.first = i;
iesire.second = j;
break; } } }
delete[] buf; }
void fa_distdrag(mat<int>& distdrag, queue<pair<int, int> >& dragoni){
pair<int, int> cur, next;
while(!dragoni.empty()){
cur = dragoni.front();
dragoni.pop();
for(int i = 0; i < 4; ++i){
next.first = cur.first + dl[i];
next.second = cur.second + dc[i];
if(distdrag[next] == gol){
distdrag[next] = distdrag[cur] + 1;
dragoni.push(next); } } } }
bool fa_distpaft(mat<int>& distpaft, const mat<int>& distdrag,
const pair<int, int>& paftenie, const pair<int, int>& iesire){
distpaft[paftenie] = distdrag[paftenie];
priority_queue<comanda> de_viz;
de_viz.push(comanda{paftenie, distpaft[paftenie]});
comanda cur, next;
while((!de_viz.empty()) && cur.p != iesire){
cur = de_viz.top();
de_viz.pop();
if(distpaft[cur] == cur.val){
for(int i = 0; i < 4; ++i){
next.p.first = cur.p.first + dl[i];
next.p.second = cur.p.second + dc[i];
next.val = min(cur.val, distdrag[next]);
if(distpaft[next] != blocat && distpaft[next] < next.val){
distpaft[next] = next.val;
de_viz.push(next); } } } } }
int main(){
ifstream f("barbar.in");
ofstream g("barbar.out");
int n, m;
f >> n >> m;
mat<int> distdrag(n+2, m+2), distpaft(n+2, m+2);
distdrag.edge(blocat);
distpaft.edge(blocat);
queue<pair<int, int> > dragoni;
pair<int, int> paftenie, iesire;
citeste_mat(f, n, m, distdrag, distpaft, dragoni, paftenie, iesire);
fa_distdrag(distdrag, dragoni);
fa_distpaft(distpaft, distdrag, paftenie, iesire);
if(distpaft[iesire] < 0){
g << "-1"; }
else{
g << distpaft[iesire]; }
return 0; }