#include <algorithm>
#include <cmath>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

using namespace std;

#define LOG(...) printf(__VA_ARGS__)
//#define LOG(...)
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) for(int i=0;i<(int)(n);++i)
#define ALL(a) (a).begin(),(a).end()
#define RALL(a) (a).rbegin(),(a).rend()
#define EXIST(s,e) ((s).find(e)!=(s).end())
#define SORT(c) sort((c).begin(),(c).end())
#define RSORT(c) sort((c).rbegin(),(c).rend())
#define CLR(a) memset((a), 0 ,sizeof(a))

typedef long long ll;
typedef unsigned long long ull;
typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<vb> vvb;
typedef vector<vi> vvi;
typedef vector<vll> vvll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

#define MAX_W 30
#define MAX_H 60

#define INF INT_MAX

int w, h;
char field[MAX_H][MAX_W];

int d[MAX_H][MAX_W][2];

const int dx[] = {1,   1, 1, 1, 1,  2, 2, 2, 3};
const int dy[] = {-2, -1, 0, 1, 2, -1, 0, 1, 0};

struct P {
    int x, y;
    int foot;
    int cost;

    bool operator >(const P& p) const {
        return cost > p.cost;
    }
};

int main() {
    while (cin >> w >> h, w|h) {
        fill_n((char *)field, MAX_W * MAX_H, 0);
        vector<pii> start, goal;
        REP(y, h) REP(x, w) {
            cin >> field[y][x];
            if (field[y][x] == 'S') {
                start.push_back(make_pair(x, y));
            }
            if (field[y][x] == 'T') {
                goal.push_back(make_pair(x, y));
            }
        }

        priority_queue<P, vector<P>, greater<P> > que;

        fill_n((int *)d, MAX_W * MAX_H * 2, INF);
        REP(i, start.size()) {
            int x = start[i].first;
            int y = start[i].second;
            d[y][x][0] = 0;
            d[y][x][1] = 0;
            que.push((P){x, y, -1, 0});
            que.push((P){x, y, 1, 0});
        }

        bool ok = false;
        while (!que.empty()) {
            P p = que.top(); que.pop();

            REP(i, goal.size()) {
                int gx = goal[i].first;
                int gy = goal[i].second;
                if (p.x == gx && p.y == gy) {
                    cout << p.cost << endl;
                    ok = true;
                    break;
                }
            }
            if (ok) break;


            int footi = (p.foot + 1) / 2;
            if (d[p.y][p.x][footi] < p.cost) continue;
            REP(i, 9) {
                int sx = p.x + dx[i] * p.foot;
                int sy = p.y + dy[i];
                if (0 <= sx && sx < w && 0 <= sy && sy < h) {
                    if (field[sy][sx] == 'T') {
                        que.push((P){sx, sy, 0, p.cost});
                    } else if ('0' <= field[sy][sx] && field[sy][sx] <= '9') {
                        int time = field[sy][sx] - '0';
                        if (d[sy][sx][1-footi] > p.cost + time) {
                            d[sy][sx][1-footi] = p.cost + time;
                            que.push((P){sx, sy, p.foot * -1, p.cost + time});
                        }
                    }
                }
            }
        }
        if (!ok) {
            cout << "-1" << endl;
        }
    }
}

Measured memory_bytes: 1252