#include <stdio.h>
#include <iostream>
#include <vector>
#include <list>
#include <cmath>
#include <fstream>
#include <algorithm>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <complex>
#include <iterator>
#include <cstdlib>
#include <sstream>

using namespace std;

#define EPS (1e-10)
#define EQ(a,b) (abs((a) - (b)) < EPS)
#define EQV(a,b) (EQ((a).real(),(b).real()) && EQ((a).imag(),(b).imag()))

//typedef complex<double> P;
typedef long long ll;

const int MAX_SIZE = 10000;

struct edge{
	int x;
	int y;
	int cost;
};

class Sit{
public:
	int x;
	int y;
	int foot;

	Sit();

	Sit(int _x,int _y,int _foot){
		x = _x;
		y = _y;
		foot = _foot;
	}

	bool operator<(const Sit &a) const{
		return a.foot < this->foot;
	}
};

typedef pair<int,Sit> P;
int V;

const int MAX_X = 30;
const int MAX_Y = 60;

// x,yÀWAÇÌ«ð©¯é©
vector<edge> G[MAX_Y][MAX_X][2];

// RXg
int d[MAX_Y][MAX_X][2];
const int INF = 100000000;

void dijkstra(int sx,int sy,int sfoot){
	priority_queue<P,vector<P>,greater<P> > que;
	for(int i = 0; i < MAX_Y; i++)
		for(int j = 0; j < MAX_X; j++)
			fill(d[i][j],d[i][j]+2,INF);

	d[sy][sx][sfoot] = 0;
	que.push(P(0,Sit(sx,sy,sfoot)));
	while(!que.empty()){
		//if(sy == 9 && que.top().second.y == 4){
		//	cout << endl;
		//}
		P p = que.top();
		que.pop();
		Sit v = p.second;
		if(d[v.y][v.x][v.foot] < p.first)
			continue;
		for(int i = 0; i < G[v.y][v.x][v.foot].size(); i++){
			edge e = G[v.y][v.x][v.foot][i];
			int nextStep = v.foot ? 0 : 1;
			if(d[e.y][e.x][nextStep] > d[v.y][v.x][v.foot] + e.cost){
				d[e.y][e.x][nextStep] = d[v.y][v.x][v.foot] + e.cost;
				que.push(P(d[e.y][e.x][nextStep],Sit(e.x,e.y,nextStep)));
			}
		}
	}


}

int main(){

	int w,h;
	char field[60][30];
	vector<pair<int,int> > startPoints;
	vector<pair<int,int> > terminates;
	while(cin >> w >> h && !(w == 0 && h == 0)){
		startPoints.clear();
		terminates.clear();
		for(int i = 0; i < MAX_Y; i++)
			for(int j = 0; j < MAX_X; j++)
				for(int k = 0; k <= 1; k++)
					G[i][j][k].clear();

		// make filed
		for(int i = 0; i < h; i++){
			for(int j = 0; j < w; j++){
				cin >> field[i][j];
				if(field[i][j] == 'S'){
					startPoints.push_back(make_pair(i,j));
				}
				else if(field[i][j] == 'T'){
					terminates.push_back(make_pair(i,j));
				}
			}
		}
		// GbWðÔ
		for(int i = 0; i < h; i++){
			for(int j = 0; j < w; j++){
				if(field[i][j] == 'X' || field[i][j] == 'T')
					continue;
				// »m[hÅÂ¢Ä¢é«Ìûü(0ð¶,1ðE«Æ·é)
				for(int k = 0; k <= 1; k++){
					if(k == 0){
						// yoko
						for(int l = 1; l <= 3; l++){
							// tate
							for(int m = -3+l; m <= -l+3; m++){
								edge e;
								e.y = i + m;
								e.x = j + l;
								if(!(e.x < 0 || e.x >= w || e.y < 0 || e.y >= h || field[e.y][e.x] == 'X' || field[e.y][e.x] == 'S')){
									if(field[e.y][e.x] == 'T')
										e.cost = 0;
									else
										e.cost = field[e.y][e.x] - '0';
									G[i][j][k].push_back(e);
								}
							}
						}
					}
					else{
						for(int l = -1; l >= -3; l--){
							// tate
							for(int m = -l-3; m <= l+3; m++){
								edge e;
								e.y = i + m;
								e.x = j + l;
								if(!(e.x < 0 || e.x >= w || e.y < 0 || e.y >= h || field[e.y][e.x] == 'X' || field[e.y][e.x] == 'S')){
									if(field[e.y][e.x] == 'T')
										e.cost = 0;
									else
										e.cost = field[e.y][e.x] - '0';
									G[i][j][k].push_back(e);
								}
							}
						}
					}
				}
			}
		}
		// en_©çD«È«ÅX^[g
		int minCost = INF;
		for(int i = 0; i < startPoints.size(); i++){
			for(int k = 0; k <= 1; k++){
				pair<int,int> pr = startPoints[i];
				dijkstra(pr.second,pr.first,k);
				// min cost
				for(int l = 0; l < terminates.size(); l++){
					for(int m = 0; m < 2; m++){
						minCost = min(minCost,d[terminates[l].first][terminates[l].second][m]);
					}
				}
			}
		}
		if(minCost == INF)
			cout << -1 << endl;
		else
			cout << minCost << endl;
	}

	return 0;
}

Measured memory_bytes: 1632