#[allow(unused_imports)]
use std::io::{stdin, Read, StdinLock};
#[allow(unused_imports)]
use std::cmp::{max, min, Ordering};
#[allow(unused_imports)]
use std::str::FromStr;
#[allow(unused_imports)]
use std::collections::{HashSet, HashMap, BinaryHeap};
#[allow(unused_imports)]
use std::vec::Vec;

#[allow(dead_code)]
const INF: i32 = 1000_000_000;
#[allow(dead_code)]
const INFLL: i64 = 1000_000_000_000_000_000;
#[allow(dead_code)]
const EPS: f64 = 1.0e-10;
#[allow(dead_code)]
const MOD: i32 = 1000_000_007;
#[allow(dead_code)]
const MODLL: i64 = 1000_000_007;

struct Scanner<'a> {
    cin: StdinLock<'a>,
}

impl<'a> Scanner<'a> {
    #[allow(dead_code)]
    fn new(cin: StdinLock<'a>) -> Scanner<'a> {
        Scanner {cin: cin}
    }

    #[allow(dead_code)]
    fn read1<T: FromStr>(&mut self) -> Option<T> {
        let token = self.cin.by_ref().bytes().map(|c| c.unwrap() as char)
                    .skip_while(|c| c.is_whitespace())
                    .take_while(|c| !c.is_whitespace())
                    .collect::<String>();
        token.parse::<T>().ok()
    }

    #[allow(dead_code)]
    fn read<T: FromStr>(&mut self) -> T {
        self.read1().unwrap()
    }
}


fn main() {
    let cin = stdin();
    let cin = cin.lock();
    let mut sc = Scanner::new(cin);

    let h: usize = sc.read();
    let w: usize = sc.read();
    let mut map: Vec<Vec<char>> = vec![Vec::new(); h];
    for i in 0..h {
        let s: String = sc.read();
        map[i] = s.chars().collect();
    }
    let map = map;
    let mut val: Vec<Vec<i32>> = vec![vec![0; w]; h];
    for i in 0..h {
        for j in 0..w {
            if map[i][j] == '.' {
                val[i][j] = 0;
            } else {
                val[i][j] = (map[i][j].to_digit(10)).unwrap() as i32;
            }
        }
    }
    let val = val;

    let mut dp: Vec<Vec<Vec<i32>>> = vec![vec![vec![INF; 1 << 4]; w]; h];
    dp[0][0][0] = 0;
    for i in 0..h {
        for j in 0..w {
            for b in 0..(1 << 4) {
                if i + 1 < h { // go down
                    let (ny, nx) = (i + 1, j);
                    let mut pay = 0;
                    if b & (1 << 1) == 0 {
                        pay += val[ny][nx];
                    }
                    let mut v: Vec<(i32, usize)> = Vec::new();
                    let nb = 0b0110 | ((b & (1 << 2)) << 1);
                    if ny + 1 < h {
                        v.push((val[ny + 1][nx], (1 << 1)));
                        pay += val[ny + 1][nx];
                    }
                    if nx + 1 < w {
                        v.push((val[ny][nx + 1], (1 << 2)));
                        pay += val[ny][nx + 1];
                    }
                    if nx != 0 && b & (1 << 0) == 0 {
                        v.push((val[ny][nx - 1], INF as usize));
                        pay += val[ny][nx - 1];
                    }

                    if v.len() == 0 {
                        dp[ny][nx][nb] = min(dp[ny][nx][nb], dp[i][j][b] + pay);
                    }
                    for (nobuy, bb) in v {
                        let nb = if bb == INF as usize { nb } else { nb ^ bb };
                        dp[ny][nx][nb] = min(dp[ny][nx][nb], dp[i][j][b] + pay - nobuy);
                    }
                }

                if j + 1 < w { // go right
                    let (ny, nx) = (i, j + 1);
                    let mut pay = 0;
                    if b & (1 << 2) == 0 {
                        pay += val[ny][nx];
                    }
                    let mut v: Vec<(i32, usize)> = Vec::new();
                    let nb = 0b0110 | ((b & (1 << 1)) >> 1);
                    if ny + 1 < h {
                        v.push((val[ny + 1][nx], 1 << 1));
                        pay += val[ny + 1][nx];
                    }
                    if nx + 1 < w {
                        v.push((val[ny][nx + 1], 1 << 2));
                        pay += val[ny][nx + 1];
                    }
                    if ny != 0 && b & (1 << 3) == 0 {
                        v.push((val[ny - 1][nx], INF as usize));
                        pay += val[ny - 1][nx];
                    }

                    if v.len() == 0 {
                        dp[ny][nx][nb] = min(dp[ny][nx][nb], dp[i][j][b] + pay);
                    }
                    for (nobuy, bb) in v {
                        let nb = if bb == INF as usize { nb } else { nb ^ bb };
                        dp[ny][nx][nb] = min(dp[ny][nx][nb], dp[i][j][b] + pay - nobuy);
                    }
                }
            }
        }
    }
    println!("{}", dp[h - 1][w - 1].iter().min().unwrap());
}


Measured memory_bytes: 105384