#include <bits/stdc++.h>
using namespace std;
struct RadixHeap {
using U = unsigned int;
vector<pair<U,int>> b[33];
U last = 0;
bool empty() const { for (int i = 0; i < 33; ++i) if (!b[i].empty()) return false; return true; }
void push(U key, int val) {
int idx = (key == last) ? 0 : 32 - __builtin_clz(key ^ last);
b[idx].push_back({key, val});
}
pair<U,int> pop() {
if (b[0].empty()) {
int i = 1; while (b[i].empty()) ++i;
U nl = UINT_MAX;
for (auto &p : b[i]) if (p.first < nl) nl = p.first;
for (auto &p : b[i]) {
int idx = (p.first == nl) ? 0 : 32 - __builtin_clz(p.first ^ nl);
b[idx].push_back(p);
}
b[i].clear();
last = nl;
}
auto res = b[0].back(); b[0].pop_back(); return res;
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
if (!(cin >> n >> m)) return 0;
vector<string> g(n);
for (int i = 0; i < n; ++i) cin >> g[i];
int N = n * m;
vector<int> a(N);
for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) a[i*m + j] = g[i][j] - '0';
vector<int> border[4];
for (int j = 0; j < m; ++j) border[0].push_back(j);
for (int j = 0; j < m; ++j) border[1].push_back((n-1)*m + j);
for (int i = 0; i < n; ++i) border[2].push_back(i*m);
for (int i = 0; i < n; ++i) border[3].push_back(i*m + (m-1));
vector<array<int,4>> nei(N);
for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) {
int id = i*m + j;
nei[id][0] = (i ? id - m : -1);
nei[id][1] = (i + 1 < n ? id + m : -1);
nei[id][2] = (j ? id - 1 : -1);
nei[id][3] = (j + 1 < m ? id + 1 : -1);
}
const int INF = 0x3f3f3f3f;
long long ans = INF;
const int S = 16;
vector<int> w(N);
vector<int> dist(S * N);
vector<uint16_t> have(N);
for (int c = 0; c <= 9; ++c) {
for (int i = 0; i < N; ++i) w[i] = abs(a[i] - c);
fill(dist.begin(), dist.end(), INF);
fill(have.begin(), have.end(), 0);
RadixHeap pq;
for (int b = 0; b < 4; ++b) {
int mk = 1 << b;
int base = mk * N;
for (int v : border[b]) {
int idx = base + v;
if (w[v] < dist[idx]) { dist[idx] = w[v]; pq.push((unsigned)w[v], idx); }
}
}
while (!pq.empty()) {
auto [du, id] = pq.pop();
if ((int)du != dist[id]) continue;
int mask = id / N, v = id % N;
uint16_t hv = have[v];
if (hv) {
for (int k = 1; k < S; ++k) if (hv & (1u << k)) {
int nm = mask | k, idx = nm * N + v;
int nd = (int)du + dist[k * N + v] - w[v];
if (nd < dist[idx]) { dist[idx] = nd; pq.push((unsigned)nd, idx); }
}
}
have[v] |= (1u << mask);
int u = v;
int nb;
nb = nei[u][0]; if (nb != -1) { int idx2 = mask * N + nb; int nd = (int)du + w[nb]; if (nd < dist[idx2]) { dist[idx2] = nd; pq.push((unsigned)nd, idx2); } }
nb = nei[u][1]; if (nb != -1) { int idx2 = mask * N + nb; int nd = (int)du + w[nb]; if (nd < dist[idx2]) { dist[idx2] = nd; pq.push((unsigned)nd, idx2); } }
nb = nei[u][2]; if (nb != -1) { int idx2 = mask * N + nb; int nd = (int)du + w[nb]; if (nd < dist[idx2]) { dist[idx2] = nd; pq.push((unsigned)nd, idx2); } }
nb = nei[u][3]; if (nb != -1) { int idx2 = mask * N + nb; int nd = (int)du + w[nb]; if (nd < dist[idx2]) { dist[idx2] = nd; pq.push((unsigned)nd, idx2); } }
}
int best = INF;
for (int v = 0; v < N; ++v) best = min(best, dist[15 * N + v]);
ans = min<long long>(ans, best);
}
cout << ans << '\n';
return 0;
}