//http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1150&lang=jp
#include <iostream>
#include <vector>
#include <queue>

#define INF (1 << 29)

using namespace std;

int w, h;
int graph[60][30];

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

int get_cost(int y, int x)
{
    return graph[y][x];
}

int c2i(char c)
{
	if(isdigit(c))
	{
		return (int)c - 48;
	}
	if(c == 'S')return 0;
	if(c == 'T')return -10;
	if(c == 'X')return INF;

	cout << "????????? : " << c << endl;
	return 100;
}

bool isValid(int y, int x)
{
	bool ret = true;
	ret &= (y < h && y >= 0);
	ret &= (x < w && x >= 0);
	if(ret)ret &= (graph[y][x] != INF);
	return ret;
}

// n?¬??????????????????????????¬¬????????°???????????????????????¨???????????????????????????
template<typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val){
    std::fill( (T*)array, (T*)(array+N), val );
}


class Path
{
public:
    Path(bool _is_right, int _x, int _y, int _cost)
    {
		is_right = _is_right;
        x = _x;
		y = _y;
        cost = _cost;
    }
	bool is_right;
    int x, y;
    int cost;
    bool operator < (const Path& other) const //??????const???????????¨priority_queue??§??¨???????????????
    {
        return this->cost < other.cost;
    }
    bool operator > (const Path& other) const //??????const???????????¨priority_queue??§??¨???????????????
    {
        return !(*this < other);
    }
};

int main()
{

	while(true)
	{
		cin >> w >> h;
		if(w == 0)break;

		for(int _h = 0; _h < h; ++_h)
		{
			for(int _w = 0; _w < w; ++_w)
			{
				char tmp;
				cin >> tmp;
				graph[_h][_w] = c2i(tmp);
			}
		}

		/*
		for(int _h = 0; _h < h; ++_h)
		{
			for(int _w = 0; _w < w; ++_w)
			{
				if(graph[_h][_w] != INF)
				cout << graph[_h][_w] << " ";
				else cout << "X ";
			}
			cout << endl;
		}
		//*/

	    int start = 0;

    	//??????????????????????°??????????
		//0:???   1:???
    	int min_cost[2][60][30];
    	Fill(min_cost, INF);

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


    	for(int _w = 0; _w < w; ++_w)
		{
			if(graph[h - 1][_w]	== 0)
			{
				min_cost[0][h-1][_w] = min_cost[1][h-1][_w] = 0;
		    	que.push( Path(0, _w, h-1, 0) );
		    	que.push( Path(1, _w, h-1, 0) );
			}
		}

		int answer = INF;

	    while(!que.empty())
	    {
	        Path now = que.top();
	        que.pop();

    	    //???????????????????°????????????????????????°?????????
    	    if(min_cost[now.is_right][now.y][now.x] < now.cost)continue;


			for(int i = 0; i < 9; ++i)
			{
				//?§??????§???????????£???????????????
				int next_x = now.x + dx[i] * (now.is_right ? -1 : 1);
				int next_y = now.y + dy[i];

				if(!isValid(next_y, next_x))continue;

				if(graph[next_y][next_x] == -10)
				{
					answer = min(answer, now.cost);
					//cout << now.x << " " << now.y << " " << answer << endl;
					continue;
				}
 
    	        //??????????????????????????????i????????????????????????????????????min_cost??????????°????????????°??´??°
       	    	int next_cost = now.cost + get_cost(next_y, next_x);
	    	    if(min_cost[!now.is_right][next_y][next_x] > next_cost)
   		        {
   	    	 	    min_cost[!now.is_right][next_y][next_x] = next_cost;
        		    que.push( Path(!now.is_right, next_x, next_y, next_cost) );
				}
	        }
	    }
		cout << ((answer == INF) ? -1 : answer) << endl;
	}

    return 0;
}

Measured memory_bytes: 3112