#include <bits/stdc++.h>
#define endl '\n'
//#define int ll
#define ve vector
#define pb push_back
#define all(x) x.begin() , x.end()
#define pii pair <int , int>
#define F first
#define S second
#define bpp __builtin_popcount

using namespace std;
typedef long long ll;
typedef long double ld;

const int N = 2e5 + 10;
int n, m;
struct slime {
    vector < int > x;
    vector < int > y;
};
void fil(slime &a) {
    a.x.resize(5);
    a.y.resize(5);
}
int mi[4] = {1, -1, 0, 0};
int mj[4] = {0, 0, 1, -1};
int mx[8] = {1, -1, 0, 0, 1, -1, 1, -1};
int my[8] = {0, 0, 1, -1, 1, -1, -1, 1};
bool check(slime a) {
    map < pii, int > mp;
    array < array < bool, 5 >, 5 > g;
    for (int i = 1; i <= 4; i++) {
        mp[{a.x[i], a.y[i]}] = i;
    }
    for (int i = 1; i <= 4; i++) {
        for (int k = 0; k < 4; k++) {
            int i2 = a.x[i] + mi[k];
            int j2 = a.y[i] + mj[k];
            if (i2 >= 0 && i2 < n && j2 >= 0 && j2 < m && mp.count({i2, j2})) {
                g[i][mp[{i2, j2}]] = 1;
                g[mp[{i2, j2}]][i] = 1;
            }
        }
    }
    queue < int > q;
    q.push(1);
    bool used[5];
    fill(used, used + 5, 0);
    used[1] = 1;
    while (!q.empty()) {
        int v = q.front();
        q.pop();
        for (int to = 1; to <= 5; to++) {
            if (g[v][to] == 1 && !used[to]) {
                used[to] = 1;
                q.push(to);
            }
        }
    }
    for (int i = 1; i <= 4; i++) {
        if (!used[i]) return 0;
    }
    return 1;
}
array < array < bool, 5 >, 5 > convert (slime a) {
    map < pii, int > mp;
    array < array < bool, 5 >, 5 > g;
    for (int i = 1; i <= 4; i++) {
        mp[{a.x[i], a.y[i]}] = i;
    }
    for (int i = 1; i <= 4; i++) {
        for (int k = 0; k < 4; k++) {
            int i2 = a.x[i] + mi[k];
            int j2 = a.y[i] + mj[k];
            if (i2 >= 0 && i2 < n && j2 >= 0 && j2 < m && mp.count({i2, j2})) {
                g[i][mp[{i2, j2}]] = 1;
                g[mp[{i2, j2}]][i] = 1;
            }
        }
    }
    return g;
}
set < slime > st;
int32_t main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    #ifdef LOCAL
        freopen("input.txt" , "r" , stdin);
        freopen("output.txt" , "w" , stdout);
    #endif // LOCAL
    cin >> n >> m;
    char a[n + 1][m + 1];
    map < array < array < bool, 5 >, 5 > , int > rast[n + 1][m + 1];
    map < array < array < bool, 5 >, 5 > , bool > used[n + 1][m + 1];
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> a[i][j];
        }
    }
    slime tek;
    fil(tek);
    tek.x[1] = 1;
    tek.y[1] = 1;

    tek.x[2] = 1;
    tek.y[2] = 2;

    tek.x[3] = 2;
    tek.y[3] = 1;

    tek.x[4] = 2;
    tek.y[4] = 2;
    queue < slime > q;
    q.push(tek);
    while (!q.empty()) {
        slime sl = q.front();
        q.pop();
        map < pii, int > was;
        for (int i = 1; i <= 5; i++) {
            was[{sl.x[i], sl.y[i]}] = 1;
        }
        for (int i = 1; i <= 4; i++) {
            for (int k = 0; k < 8; k++) {
                int i2 = sl.x[i] + mx[k];
                int j2 = sl.y[i] + my[k];
                if (was[{i2, j2}]) continue;
                if (i2 >= 1 && i2 <= n && j2 >= 1 && j2 <= m && a[i2][j2] == '.') {
                    pii d = {sl.x[i], sl.y[i]};
                    sl.x[i] = i2;
                    sl.x[i] = j2;
                    if (!check(sl)) continue;
                //    st.insert(sl);
                    array < array < bool, 5 >, 5 > nw = convert(sl);
                    if (used[i2][j2][nw]) continue;
                    sl.x[i] = d.F;
                    sl.y[i] = d.S;
                    array < array < bool, 5 >, 5 > old = convert(sl);
                    rast[i2][j2][nw] = min(rast[i2][j2][nw], rast[sl.x[i]][sl.y[i]][old] + 1);\
                    used[i2][j2][nw] = 1;
                    sl.x[i] = i2;
                    sl.x[i] = j2;
                    q.push(sl);
                    sl.x[i] = d.F;
                    sl.y[i] = d.S;
                }
            }
        }
    }
    vector < int > nums(4);
    nums[0] = 1;
    nums[1] = 2;
    nums[2] = 3;
    nums[3] = 4;
    pii cor[5];
    cor[1] = {n, m};
    cor[2] = {n - 1, m};
    cor[3] = {n, m - 1};
    cor[4] = {n - 1, m - 1};
    int ans = (int)(1e9);
  //  cout << rast[3][2][3] << " " << rast[2][2][4] << " " << rast[2][3][1] << " " << rast[3][3][2] << endl;
  //  return 0;
    do {
        int sum = 0;
        slime nw;
        for (int i = 0; i < nums.size(); i++) {
            nw.x[i + 1] = cor[nums[i]].F;
            nw.y[i + 1] = cor[nums[i]].S;
        }
        array < array < bool, 5 >, 5 > tk = convert(nw);
        for (auto to : nums) {
          //  cout << to << " " << cor[to].F << " " << cor[to].S << " " << rast[cor[to].F][cor[to].S][to] << endl;
            sum += rast[cor[to].F][cor[to].S][tk];
        }
        ans = min(ans, sum);
    //    return 0;
    }while(next_permutation(nums.begin(), nums.end()));
    cout << ans;
    return 0;
}
