#include <fstream>
#include <vector>
#include <queue>
#include <tuple>
using namespace std;
ifstream fin("barbar.in");
ofstream fout("barbar.out");
const int di[] = {-1, 1, 0, 0},
dj[] = {0, 0, -1, 1},
Inf = 1e6,
N = 1007;
using PI = pair<int, int>;
using VI = vector<int>;
using VVI = vector<VI>;
using VB = vector<bool>;
using VVB = vector<VB>;
VVI d;
VVB v;
VVB mat;
int n, m;
int ip, jp, is, js;
vector<PI> dragoni;
void CitesteDate();
bool ok1(int i, int j);
bool ok2(int i, int j, int D);
void DistMinFataDeDragoni();
bool PoateTrece(int X);
int CautBinDistMax();
int main()
{
CitesteDate();
DistMinFataDeDragoni();
int dmax = CautBinDistMax();
fout << dmax;
return 0;
}
int CautBinDistMax()
{
int st = 1, dr = N, m, dmax = -1;
while (st <= dr)
{
m = st + (dr - st) / 2;
if (PoateTrece(m))
{
dmax = max(dmax, m);
st = m + 1;
}
else
dr = m - 1;
}
// if (d[ip][jp] < dmax)
// dmax = d[ip][jp];
return dmax;
}
bool ok2(int i, int j, int D)
{
if (i < 1 || i > n || j < 1 || j > m)
return false;
if (mat[i][j])
return false;
if (v[i][j]) // celula vizitata anterior
return false;
if (d[i][j] < D) // daca se apropie de un dragon la dist ma mica decat D
return false;
return true;
}
#define iv (i + di[p])
#define jv (j + dj[p])
bool PoateTrece(int D)
{
queue<PI> Q;
v = VVB(n + 1, VB(m + 1));
v[ip][jp] = true;
Q.emplace(ip, jp);
int i, j;
while (!Q.empty())
{
tie(i, j) = Q.front();
Q.pop();
for (int p = 0; p < 4; ++p)
if (ok2(iv, jv, D))
{
v[iv][jv] = true;
if (iv == is && jv == is)
return true;
Q.emplace(iv, jv);
}
}
return false;
}
void DistMinFataDeDragoni()
{
queue<PI> Q;
d = VVI(n + 1, VI(m + 1, Inf));
int i, j;
for(auto &dragon: dragoni)
{
tie(i, j) = dragon;
d[i][j] = 0;
Q.push(dragon);
}
while (!Q.empty())
{
tie(i, j) = Q.front();
Q.pop();
for(int p = 0; p < 4; ++p)
if (ok1(iv, jv) && d[iv][jv] > d[i][j] + 1)
{
d[iv][jv] = d[i][j] + 1;
Q.emplace(iv, jv);
}
}
}
bool ok1(int i, int j)
{
if (i < 1 || i > n || j < 1 || j > m)
return false;
if (mat[i][j]) return false;
return true;
}
void CitesteDate()
{
fin >> n >> m;
mat = VVB(n + 1, VB(m + 1));
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
{
char c;
fin >> c;
if (c == '*')
mat[i][j] = true;
if (c == 'I')
{
ip = i;
jp = j;
}
if (c == 'O')
{
is = i;
js = j;
}
if (c == 'D')
{
dragoni.emplace_back(i, j);
}
}
}