#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <mutex>
using namespace std;

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<char> vc;
typedef vector<vc> vvc;
typedef pair<int, int> P;

struct position {
	int i, j;

	position(int i, int j) :i(i), j(j){
	}
};

struct edge {
	int to, cost;

	edge(int to, int cost) :to(to), cost(cost){
	};
};

const int MAX_V = 3600;
const int INF = 9999999;

int dxl[] = {1, 1, 1, 1, 1, 2, 2, 2, 3}, dyl[] = {-2, -1, 0, 1, 2, -1, 0, 1, 0};
int dxr[] = {-1, -1, -1, -1, -1, -2, -2, -2, -3}, dyr[] = {-2, -1, 0, 1, 2, -1, 0, 1, 0};

int d[MAX_V];
int V;
vector<edge> G[MAX_V];

int h, w;

bool in(int i, int j){
	return 0 <= i && i < h && 0 <= j && j < w;
}

int toV(int i, int j, int foot){
	return 2 * (i * w + j) + foot;
}

void calc(int s){
	priority_queue<P, vector<P>, greater<P>> que;
	fill(d, d + V, INF);
	d[s] = 0;
	que.push(P(0, s));

	while (!que.empty()) {
		P p = que.top();
		que.pop();
		int v = p.second;
		if (d[v] < p.first) continue;
		for (auto&& e : G[v]) {
			if (d[e.to] > d[v] + e.cost) {
				d[e.to] = d[v] + e.cost;
				que.push(P(d[e.to], e.to));
			}
		}
	}
}

int main(){
	while (cin >> w >> h , w != 0 || h != 0) {
		auto s = vvc(h, vc(w, 0));
		for (int i = 0; i < h; i++)
			for (int j = 0; j < w; j++)
				cin >> s[i][j];

		V = w * h * 2;

		auto start = vector<position>();
		auto goal = vector<position>();
		for (int i = 0; i < h; i++)
			for (int j = 0; j < w; j++) {
				if (s[i][j] == 'S') start.push_back(position(i, j));
				else if (s[i][j] == 'T') goal.push_back(position(i, j));
			}

		for (int i = 0; i < MAX_V; i++)
			G[i].clear();

		for (int i = 0; i < h; i++) {
			for (int j = 0; j < w; j++) {
				// left foot
				for (int k = 0; k < 9; k++) {
					int ni = i + dyl[k], nj = j + dxl[k];
					if (!in(ni, nj)) continue;
					if ('1' <= s[ni][nj] && s[ni][nj] <= '9')
						G[toV(i, j, 0)].push_back(edge(toV(ni, nj, 1), s[ni][nj] - '0'));
					else if (s[ni][nj] == 'S' || s[ni][nj] == 'T')
						G[toV(i, j, 0)].push_back(edge(toV(ni, nj, 1), 0));
				}
				// right foot
				for (int k = 0; k < 9; k++) {
					int ni = i + dyr[k], nj = j + dxr[k];
					if (!in(ni, nj)) continue;
					if ('1' <= s[ni][nj] && s[ni][nj] <= '9')
						G[toV(i, j, 1)].push_back(edge(toV(ni, nj, 0), s[ni][nj] - '0'));
					else if (s[ni][nj] == 'S' || s[ni][nj] == 'T')
						G[toV(i, j, 1)].push_back(edge(toV(ni, nj, 0), 0));
				}
			}
		}

		int ans = INF;
		for (auto&& sp : start) {
			calc(toV(sp.i, sp.j, 0));
			for (auto&& gp : goal) {
				ans = min(ans, d[toV(gp.i, gp.j, 0)]);
				ans = min(ans, d[toV(gp.i, gp.j, 1)]);
			}
			calc(toV(sp.i, sp.j, 1));
			for (auto&& gp : goal) {
				ans = min(ans, d[toV(gp.i, gp.j, 0)]);
				ans = min(ans, d[toV(gp.i, gp.j, 1)]);
			}
		}

		if (ans == INF)
			cout << -1 << endl;
		else
			cout << ans << endl;

	}
}