use std::hash::Hash;
use std::collections::hash_set::Iter;
use std::rc::Rc;
use std::ops::DivAssign;
use std::ops::MulAssign;
use std::ops::SubAssign;
use std::collections::BinaryHeap;
use std::str::FromStr;
use std::collections::HashSet;
use std::collections::BTreeMap;
use std::fmt::Display;
use std::ops::Neg;
use std::ops::Div;
use std::ops::Mul;
use std::ops::Add;
use std::ops::{AddAssign, Sub};
use std::cmp::max;
use std::collections::VecDeque;
use std::cmp::min;
use std::collections::{HashMap, BTreeSet};
use std::cmp::Ordering;
use std::fmt::Debug;

fn read_line() -> String {
    let mut buffer = String::new();
    std::io::stdin().read_line(&mut buffer).expect("No Line");
    buffer.trim().to_owned()
}
fn read_lines<T: std::str::FromStr>(count: usize) -> Vec<T> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(buffer.trim().parse().ok().expect("Can't Parse"));
        buffer.clear();
    }
    vec
}
fn read_tabulate<R, T: Fn(&str)->R> (count: usize, transformer: T) -> Vec<R> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(transformer(buffer.trim()));
        buffer.clear();
    }
    vec
}
fn read_value<T: std::str::FromStr>() -> T {
    read_line().trim().parse().ok().unwrap()
}
fn read_values<T: std::str::FromStr>() -> Vec<T> {
    read_line().trim().split_whitespace().map(|x| x.parse().ok().expect("Can't Parse")).collect::<Vec<T>>()
}
macro_rules! freeze {
    ($($id:ident), *) => {
        $(let $id = $id;)*
    };
}
macro_rules! read_map {
    ($ident: ident: [$block: block; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$block: block; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
}
macro_rules! read {
    (mut $ident: ident: String) => {
        let mut $ident = read_value::<String>();
    };
    ($ident: ident: String) => {
        let $ident = read_value::<String>();
    };
    (mut $ident: ident: [$ty:ty]) => {
        let mut $ident = read_values::<$ty>();
    };
    ($ident: ident: [$ty:ty]) => {
        let $ident = read_values::<$ty>();
    };
    (mut $ident: ident: [[$ty:ty]; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| read_values::<$ty>()).collect::<Vec<_>>();
    };
    ($ident: ident: [[$ty:ty]; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| read_values::<$ty>()).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$ty:ty; $size:expr]) => {
        let mut $ident = read_lines::<$ty>($size);
    };
    ($ident: ident: [$ty:ty; $size:expr]) => {
        let $ident = read_lines::<$ty>($size);
    };
    ($ident: ident: [$block: block; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$block: block; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    ($($token: tt)*) => {
        let mut iter = read_values::<String>().into_iter();
        read_from_iter!(iter; $($token)*);
    };
}
macro_rules! read_from_iter {
    ($iter:expr; mut $ident:ident:$ty:ty, $($rest:tt)*) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; $ident:ident:$ty:ty, $($rest:tt)*) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; mut $ident:ident:$ty:ty) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter:expr; $ident:ident:$ty:ty) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter: expr; ) => {};
}
struct KeyValue<K, V> {
    key: K,
    value: V
}
impl <K: PartialOrd, V> PartialEq for KeyValue<K, V> {
    fn eq(&self, other: &Self) -> bool {
        self.key.eq(&other.key)
    }
}
impl <K: PartialOrd, V> Eq for KeyValue<K, V> {}
impl <K: PartialOrd, V> PartialOrd for KeyValue<K, V> {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        self.key.partial_cmp(&other.key)
    }
}
impl <K: PartialOrd, V> Ord for KeyValue<K, V> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.key.partial_cmp(&other.key).ok_or("Can't Compare").unwrap()
    }
}
#[derive(Eq, PartialEq)]
struct Rev<T: Ord>(T);
impl <T: std::cmp::Ord> PartialOrd for Rev<T> {
    fn partial_cmp(&self, rhs: &Rev<T>) -> std::option::Option<std::cmp::Ordering> { 
        rhs.0.partial_cmp(&self.0)
    }
}
impl <T: Ord> Ord for Rev<T> {
    fn cmp(&self, rhs: &Self) -> std::cmp::Ordering { 
        rhs.0.cmp(&self.0)
    }
}
#[derive(Copy, Clone, Debug)]
struct Coordinate{
    x: i32, y: i32
}

impl Coordinate {
    fn manhattan_distance(&self, other: Coordinate) -> i32 {
        (self.x - other.x).abs() + (self.y - other.y).abs()
    }
}
impl Add for Coordinate {
    type Output = Coordinate;
    fn add(self, rhs: Coordinate) -> <Self as std::ops::Add<Coordinate>>::Output {
        Coordinate{x: self.x + rhs.x, y: self.y + rhs.y}
    }
}
#[derive(Copy, Clone, Debug)]
enum Block {
    Start, Goal, Break, Num(i32)
}
impl FromStr for Block {
    type Err = ();
    fn from_str(s: &str) -> std::result::Result<Self, <Self as std::str::FromStr>::Err> {
        match s {
            "S" => Ok(Block::Start),
            "T" => Ok(Block::Goal),
            "X" => Ok(Block::Break),
            _ => {
                if let Ok(n) = s.parse::<i32>() {
                    Ok(Block::Num(n))
                }else {
                    Err(())
                }
            }
        }
    }
}
impl Block {
    fn is_goal(&self) -> bool {
        match self {
            &Block::Goal => true,
            _ => false
        }
    }
    fn is_start(&self) -> bool {
        match self {
            &Block::Start => true,
            _ => false
        }
    }
}
fn find_start_pos(state: &Vec<Vec<Block>>) -> Vec<Coordinate> {
    let mut res = Vec::with_capacity(2);
    for i in 0 .. state.len() {
        for j in 0 .. state[i].len() {
            match state[i][j] {
                Block::Start => res.push(Coordinate{x: j as i32, y: i as i32}),
                _ => ()
            }
        }
    }
    res
}

fn main() {
    let right_next = (1 .. 4).flat_map(|x| (-2 .. 3).map(move |y| Coordinate{x: x, y: y})).filter(|c| c.x.abs() + c.y.abs() <= 3).collect::<Vec<_>>();
    let left_next = (-3 .. 0).flat_map(|x| (-2 .. 3).map(move |y| Coordinate{x: x, y: y})).filter(|c| c.x.abs() + c.y.abs() <= 3).collect::<Vec<_>>();
    loop {
        read!(width: usize, height: usize);
        if width == 0 && height == 0 {break;}
        read!(state: [[Block]; height]);
        let mut memo = vec![vec![vec![std::i32::MAX; width]; height]; 2];
        let mut queue = BinaryHeap::new();
        for start in find_start_pos(&state) {
            queue.push(Rev(KeyValue{key: 0, value: (0, start)}));
            queue.push(Rev(KeyValue{key: 0, value: (1, start)}));
            memo[0][start.y as usize][start.x as usize] = 0;
            memo[1][start.y as usize][start.x as usize] = 0;
        }
        let mut result = None;
        while let Some(Rev(KeyValue{key: time, value: value})) = queue.pop() {
            match value {
                (0, left) => {
                    for next_right in right_next.iter().map(|&c| c + left).filter(|c| 0 <= c.x && c.x < width as i32 && 0 <= c.y && c.y < height as i32) {
                        match state[next_right.y as usize][next_right.x as usize] {
                            Block::Num(c) => {
                                if memo[1][next_right.y as usize][next_right.x as usize] > time + c {
                                    memo[1][next_right.y as usize][next_right.x as usize] = time + c;
                                    queue.push(Rev(KeyValue{key: time + c, value: (1, next_right)}));
                                }
                            }
                            Block::Break => (),
                            Block::Goal => {
                                result = Some(time);
                                break;
                            }
                            _ => {
                                if memo[1][next_right.y as usize][next_right.x as usize] > time {
                                    memo[1][next_right.y as usize][next_right.x as usize] = time;
                                    queue.push(Rev(KeyValue{key: time, value: (1, next_right)}));
                                }
                            }
                        }
                    }
                },
                (1, right) => {
                    for next_left in left_next.iter().map(|&c| c + right).filter(|c| 0 <= c.x && c.x < width as i32 && 0 <= c.y && c.y < height as i32) {
                        match state[next_left.y as usize][next_left.x as usize] {
                            Block::Num(c) => {
                                if memo[0][next_left.y as usize][next_left.x as usize] > time + c {
                                    memo[0][next_left.y as usize][next_left.x as usize] = time + c;
                                    queue.push(Rev(KeyValue{key: time + c, value: (0, next_left)}));
                                }
                            }
                            Block::Break => (),
                            Block::Goal => {
                                result = Some(time);
                                break;
                            }
                            _ => {
                                if memo[0][next_left.y as usize][next_left.x as usize] > time {
                                    memo[0][next_left.y as usize][next_left.x as usize] = time;
                                    queue.push(Rev(KeyValue{key: time, value: (0, next_left)}));
                                }
                            }
                        }
                    }
                },
                _ => panic!()
            }
            if result.is_some() {break;}
        }
        println!("{}", result.unwrap_or(-1));
    }
}


Measured memory_bytes: 5060