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

template <class T>
using MinHeap = std::priority_queue<T, std::vector<T>, std::greater<T>>;

template <class T>
std::vector<T> vec(int len, T elem) { return std::vector<T>(len, elem); }

constexpr int INF = 1 << 30;

const std::vector<int> dx{0, 1, 0, -1, 0}, dy{1, 0, -1, 0, 0};
const std::vector<int> di{0, 0, 1, 1, 2}, dj{1, 2, 0, 1, 0};

void solve() {
    int h, w;
    std::cin >> h >> w;

    auto cost = vec(h, vec(w, 0));
    for (int x = 0; x < h; ++x) {
        for (int y = 0; y < w; ++y) {
            char c;
            std::cin >> c;
            if (c != '.') cost[x][y] = c - '0';
        }
    }

    auto dist = vec(h, vec(w, vec(1 << 5, INF)));
    dist[0][0][0] = 0;
    MinHeap<std::tuple<int, int, int, int>> que;
    que.emplace(dist[0][0][0], 0, 0, 0);

    auto circ = vec(4, vec(4, false));
    while (!que.empty()) {
        int d, x, y, b;
        std::tie(d, x, y, b) = que.top();
        que.pop();
        if (dist[x][y][b] < d) continue;

        for (int l = 0; l < 5; ++l) {
            int i = di[l], j = dj[l];
            circ[i][j] = ((b >> l) & 1);
        }

        int nd = d;
        if (!circ[1][1] && cost[x][y] > 0) {
            nd += cost[x][y];
            circ[1][1] = true;
        }

        std::vector<int> att;
        for (int k = 0; k < 4; ++k) {
            int pi = dx[k] + 1, pj = dy[k] + 1;
            int px = x + dx[k], py = y + dy[k];

            if (px < 0 || h <= px || py < 0 || w <= py) continue;
            if (circ[pi][pj] || cost[px][py] == 0) continue;
            att.push_back(k);
        }

        for (int p = 0; p <= (int)att.size(); ++p) {
            for (int i = 0; i < (int)att.size(); ++i) {
                if (i == p) continue;

                int k = att[i];
                int ni = dx[k] + 1, nj = dy[k] + 1;
                int nx = x + dx[k], ny = y + dy[k];

                nd += cost[nx][ny];
                circ[ni][nj] = true;
            }

            for (int l = 0; l < 2; ++l) {
                int bi = dx[l], bj = dy[l],
                    nx = x + dx[l], ny = y + dy[l];
                if (nx < 0 || h <= nx || ny < 0 || w <= ny) continue;

                int nb = 0;
                for (int k = 0; k < 5; ++k) {
                    int i = bi + di[k], j = bj + dj[k];
                    nb |= (circ[i][j] << k);
                }

                if (dist[nx][ny][nb] <= nd) continue;
                dist[nx][ny][nb] = nd;
                que.emplace(dist[nx][ny][nb], nx, ny, nb);
            }

            for (int i = 0; i < (int)att.size(); ++i) {
                if (i == p) continue;

                int k = att[i];
                int ni = dx[k] + 1, nj = dy[k] + 1;
                int nx = x + dx[k], ny = y + dy[k];

                nd -= cost[nx][ny];
                circ[ni][nj] = false;
            }
        }
    }

    const auto& last = dist.back().back();
    std::cout << *std::min_element(last.begin(), last.end()) << std::endl;
}

int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);

    solve();

    return 0;
}



Measured memory_bytes: 171932