注意可能有公共路程
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define ll long long
#define rep(x, y, z) for(int x=y;x<z;x++)
#define lson rt<<1, L, m
#define rson rt<<1|1, m, R
typedef pair<int, int> P;
#define mp(x, y) make_pair(x, y)
#define pb(x) push_back(x)
#define fi first
#define se second
const int maxn = 1e3 + 7;
const int INF = 0x3f3f3f3f;
const int tx[] = {1, 0, -1, 0}, ty[] = {0, 1, 0, -1};
int n, m;
char g[maxn][maxn];
int d[4][4];
int dis[4][maxn][maxn];
P find(char x){
rep(i, 0, n) rep(j, 0, m) if(g[i][j] == x) return mp(i, j);
}
vector<P> ini(P p){
vector<P> res;
bool vis[maxn][maxn];
memset(vis, 0, sizeof(vis));
vis[p.fi][p.se] = 1;
queue<P> q;
q.push(p);
while(!q.empty()){
P t = q.front(); q.pop();
res.pb(t);
int x = t.fi, y = t.se;
rep(i, 0, 4)
if(x + tx[i] < n && x + tx[i] >= 0 && y + ty[i] < m && y + ty[i] >= 0 && g[x+tx[i]][y+ty[i]] == g[p.fi][p.se] && !vis[x+tx[i]][y+ty[i]]){
q.push(mp(x + tx[i], y + ty[i]));
vis[x+tx[i]][y+ty[i]] = 1;
}
}
return res;
}
struct Node{
int x, y, d;
Node(){}
Node(int a, int b, int c): x(a), y(b), d(c) {}
};
void work(int idd){
vector<P> s = ini(find(idd));
int sz = s.size();
queue<Node> q;
rep(i, 0, sz) q.push(Node(s[i].fi, s[i].se, 0));
bool vis[maxn][maxn];
memset(vis, 0, sizeof(vis));
while(!q.empty()){
Node t = q.front(); q.pop();
int x = t.x, y = t.y;
rep(i, 0, 4)
if(x + tx[i] < n && x + tx[i] >= 0 && y + ty[i] < m && y + ty[i] >= 0 && g[x+tx[i]][y+ty[i]] != '#' && !vis[x+tx[i]][y+ty[i]]){
vis[x+tx[i]][y+ty[i]] = 1;
if(g[x+tx[i]][y+ty[i]] == '.') {
q.push(Node(x+tx[i], y+ty[i], t.d+1));
dis[idd-'0'][x+tx[i]][y+ty[i]] = t.d;
}
else if(g[x+tx[i]][y+ty[i]] != idd) d[g[x+tx[i]][y+ty[i]]-'0'][idd-'0'] = d[idd-'0'][g[x+tx[i]][y+ty[i]]-'0'] = min(d[g[x+tx[i]][y+ty[i]]-'0'][idd-'0'], t.d);
}
}
}
ll ans = INF;
bool solve(){
rep(i, 1, 4) rep(j, 1, 4) rep(k, 1, 4){
if(i == j || i == k || j == k) continue;
if(d[i][j] != INF && d[j][k] != INF) ans = min(ans, (ll)d[i][j] + d[j][k]);
}
if(ans == INF) return false;
return true;
}
int main(){
#ifdef ac
freopen("in.txt","r",stdin);
#endif
//freopen("out.txt","w",stdout);
memset(d, INF, sizeof(d));
memset(dis, INF, sizeof(dis));
scanf("%d%d", &n, &m);
rep(i, 0, n) scanf("%s", g[i]);
rep(i, 1, 4) work(i+'0');
if(!solve()){
printf("-1\n");
return 0;
}
else {
rep(i, 0, n) rep(j, 0, m) ans = min(ans, (ll)dis[1][i][j]+dis[2][i][j]+dis[3][i][j]+1);
printf("%lld\n", ans);
}
return 0;
}