#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=20+5, _hash=10007, maxn=1000000+10, INF=0x7f7f7f7f;
typedef long long lint;
int n, m, code[N], ch[N], mmp[N][N];
char s[N];
struct hashmap
{
int cur, fir[_hash], nxt[maxn], f[maxn];
lint st[maxn];
void clear()
{
cur=0;
memset(fir, 0, sizeof fir);
return ;
}
void push(lint s, int ans)
{
int u=s%_hash;
for(int i=fir[u]; i; i=nxt[i]) if(st[i]==s)
{
f[i]=min(f[i], ans);
return ;
}
nxt[++cur]=fir[u], fir[u]=cur, st[cur]=s, f[cur]=ans;
return ;
}
}p[2];
void Read()
{
memset(mmp, -1, sizeof mmp);
for(int i=1; i<=n; i++)
{
scanf("%s", s+1);
for(int j=1; j<=m; j++)
{
if(s[j]=='#') mmp[i][j]=-1;
else if(s[j]=='W') mmp[i][j]=-2;
else if(s[j]=='L') mmp[i][j]=-3;
else mmp[i][j]=s[j]-'0';
}
}
return ;
}
void Decode(lint st)
{
for(int i=m; i>=0; i--)
{
code[i]=st&7;
st>>=3;
}
return ;
}
lint Encode()
{
lint st=0;
memset(ch, -1, sizeof ch);
ch[0]=0;
for(int i=0, cnt=0; i<=m; i++)
{
if(ch[code[i]]==-1) ch[code[i]]=++cnt;
code[i]=ch[code[i]];
st<<=3;
st|=code[i];
}
return st;
}
void Shift()
{
for(int i=m; i; i--) code[i]=code[i-1];
code[0]=0;
return ;
}
void DP_blank(int i, int j, int u)
{
int val=mmp[i][j], left, up, t, cnt;
for(int k=1; k<=p[u].cur; k++)
{
Decode(p[u].st[k]);
left=code[j-1], up=code[j];
if(left && up)
{
if(left!=up)
{
code[j-1]=code[j]=0;
for(int h=0; h<=m; h++) if(code[h]==up) code[h]=left;
if(j==m) Shift();
p[u^1].push(Encode(), p[u].f[k]+val);
}
}
else if(left || up)
{
t=(left ? left : up);
if(i==n)
{
cnt=0;
for(int h=0; h<j-1; h++) if(code[h]) ++cnt;
if(!cnt)
{
code[j-1]=t, code[j]=0;
if(j==m) Shift();
p[u^1].push(Encode(), p[u].f[k]+val);
}
}
else if(mmp[i+1][j]>=0)
{
code[j-1]=t, code[j]=0;
if(j==m) Shift();
p[u^1].push(Encode(), p[u].f[k]+val);
}
if(mmp[i][j+1]>=0)
{
code[j-1]=0, code[j]=t;
if(j==m) Shift();
p[u^1].push(Encode(), p[u].f[k]+val);
}
}
else
{
code[j-1]=code[j]=0;
if(j==m) Shift();
p[u^1].push(Encode(), p[u].f[k]);
if(i==n)
{
cnt=0;
for(int h=0; h<j-1; h++) if(code[h]) ++cnt;
if(cnt==0 && mmp[i][j+1]>=0)
{
code[j-1]=code[j]=13;
if(j==m) Shift();
p[u^1].push(Encode(), p[u].f[k]+val);
}
}
else if(mmp[i][j+1]>=0 && mmp[i+1][j]>=0)
{
code[j-1]=code[j]=13;
if(j==m) Shift();
p[u^1].push(Encode(), p[u].f[k]+val);
}
}
}
return ;
}
void DP_block(int i, int j, int u)
{
for(int k=1, cnt; k<=p[u].cur; k++)
{
Decode(p[u].st[k]);
if(code[j-1] || code[j]) continue;
cnt=0;
for(int h=0; h<j-1; h++) if(code[h]) ++cnt;
if(mmp[i][j]==-2 && (cnt&1)) continue;
if(mmp[i][j]==-3 && !(cnt&1)) continue;
code[j-1]=code[j]=0;
if(j==m) Shift();
p[u^1].push(Encode(), p[u].f[k]);
}
return ;
}
int Work()
{
int u=0, ans=INF;
p[u].clear();
memset(code, 0, sizeof code);
for(int i=1; i<=m; i++) if(mmp[1][i]>=0)
{
code[i]=1;
p[u].push(Encode(), 0);
code[i]=0;
}
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
{
p[u^1].clear();
if(mmp[i][j]>=0) DP_blank(i, j, u);
else DP_block(i, j, u);
u^=1;
}
for(int i=1, cnt=0; i<=p[u].cur; i++)
{
Decode(p[u].st[i]);
cnt=0;
for(int j=1; j<=m; j++) if(code[j]) ++cnt;
if(cnt==1) ans=min(ans, p[u].f[i]);
}
return (ans==INF) ? -1 : ans;
}
int main()
{
while(scanf("%d%d", &n, &m) != EOF)
{
Read();
printf("%d\n", Work());
}
return 0;
}