#include <bits/stdc++.h>
using namespace std;
#define FOR(i,k,n) for(int i = (k); i < (n); i++)
#define REP(i,n) FOR(i,0,n)
#define ALL(a) a.begin(), a.end()
#define MS(m,v) memset(m,v,sizeof(m))
#define D10 fixed<<setprecision(10)
typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;
const int INF = 114514810;
const int MOD = 1000000007;
const double EPS = 1e-10;

typedef int weight;
struct edge
{
	int to; weight cost;
	bool operator < (const edge& e) const { return cost < e.cost; }
	bool operator >(const edge& e) const { return cost > e.cost; }
};

typedef vector<edge> Edges;
typedef vector<Edges> Graph;
//int dx[] = { -1, 0, 0, 1 }; int dy[] = { 0, -1, 1, 0 };
template<class T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template<class T> T &chmax(T &a, const T &b) { return a = max(a, b); }
bool valid(int x, int y, int h, int w) { return (x >= 0 && y >= 0 && x < h&&y < w); }
int place(int x, int y, int w) { return w*x + y; }
///*************************************************************************************///
///*************************************************************************************///
///*************************************************************************************///

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

void dijkstra(Graph &g, vector<weight> &d, int s)
{
	d.assign(g.size(), INF);
	d[s] = 0;
	typedef pair<weight, int> P;
	priority_queue<P, vector<P>, greater<P>> que;
	que.push(P(0, s));
	while (!que.empty())
	{
		weight dist = que.top().first;
		int v = que.top().second;
		que.pop();
		if (d[v] < dist) continue;
		REP(i, g[v].size())
		{
			edge e = g[v][i];
			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()
{
	int w, h;
	while (cin >> w >> h, w)
	{
		vector<vi> fld(h, vi(w));
		vi st, go;
		map<pii, int> mp;
		mp[pii(-1, -1)] = -1;
		REP(i, h)REP(j, w)
		{
			char c;
			cin >> c;
			if (c == 'X') fld[i][j] = INF;
			else if (c == 'S')
			{
				fld[i][j] = 0;
				st.push_back(place(i, j, w));
			}
			else if (c == 'T')
			{
				fld[i][j] = 0;
				go.push_back(place(i, j, w));
			}
			else fld[i][j] = c - '0';
		}
		vi goal;
		Graph g(1);
		REP(i, h)REP(j, w)
		{
			int left = place(i, j, w);
			REP(k, 9)
			{
				int rx = i + dx[k], ry = j + dy[k];
				if (!valid(rx, ry, h, w)) continue;
				int right = place(rx, ry, w);
				int aaa = mp.size();
				if (find(ALL(st), left) != st.end() || find(ALL(st), right) != st.end())
				{
					g[0].push_back(edge{ aaa, max(fld[i][j], fld[rx][ry]) });
				}
				if (find(ALL(go), left) != go.end() || find(ALL(go), right) != go.end())
				{
					goal.push_back(aaa);
				}
				mp[pii(left, right)] = aaa;
			}
		}
		g.resize(mp.size());
		REP(i, h)REP(j, w)
		{
			int left = place(i, j, w);
			REP(k, 9)
			{
				int rx = i + dx[k], ry = j + dy[k];
				if (!valid(rx, ry, h, w)) continue;
				int right = place(rx, ry, w);
				int now = mp[pii(left, right)];
				REP(l, 9)
				{
					int nx = i + dx[l], ny = j + dy[l];
					if (!valid(nx, ny, h, w)) continue;
					int next = mp[pii(left, place(nx, ny, w))];
					g[now].push_back(edge{ next, fld[nx][ny] });
				}
				REP(l, 9)
				{
					int nx = rx + dx[l], ny = ry - dy[l];
					if (!valid(nx, ny, h, w)) continue;
					int next = mp[pii(place(nx, ny, w), right)];
					g[now].push_back(edge{ next, fld[nx][ny] });
				}
			}
		}
		vector<weight> d;
		dijkstra(g, d, 0);
		int ans = INF;
		REP(i, goal.size()) chmin(ans, d[goal[i]]);
		cout << (ans == INF ? -1 : ans) << endl;
	}

	return 0;
}

Measured memory_bytes: 6456