#include <iostream>
#include <queue>
#include <vector>
#include <tuple>

using namespace std;

#define ll long long

const ll MAX_COST = 999999999;

int main() {
    ll n, m;
    cin >> n >> m;
    vector<vector<ll>> grid(n, vector<ll>(m));
    vector<vector<ll>> cost(n, vector<ll>(m, MAX_COST));

    for (ll i = 0; i < n; ++i) {
        for (ll j = 0; j < m; ++j) {
            char ch;
            cin >> ch;
            grid[i][j] = (ch != '#');
        }
    }

    priority_queue<tuple<ll, ll, ll>, vector<tuple<ll, ll, ll>>, greater<>> pq;

    cost[1][1] = 0;
    pq.push({0, 1, 1});

    ll di[] = {1, -1, 0, 0, -1, -1, 1, 1};
    ll dj[] = {0, 0, 1, -1, -1, 1, -1, 1};
    ll move_cost[] = {4, 4, 4, 4, 5, 5, 5, 5};

    while (!pq.empty()) {
        auto [current_cost, i, j] = pq.top();
        pq.pop();

        if (cost[i][j] < current_cost)
            continue;

        for (int k = 0; k < 8; ++k) {
            ll ci = i + di[k];
            ll cj = j + dj[k];
            ll new_cost = current_cost + move_cost[k];

            if (ci >= 0 && ci < n && cj >= 0 && cj < m && grid[ci][cj] && new_cost < cost[ci][cj]) {
                cost[ci][cj] = new_cost;
                pq.push({new_cost, ci, cj});
            }
        }
    }

    cout << (cost[n-1][m-1] == MAX_COST ? -1 : cost[n-1][m-1]) << endl;
    return 0;
}