#include <bits/stdc++.h>
using namespace std;

const int INF = 1e9 + 10;
int w, h;

struct pos {
  int x;
  int y;
  bool is_out() { return x < 1 || w < x || y < 1 || h < y; }
};
struct node {
  pos loc;
  int time;
  int step;
  void print() {
    cout << loc.x << ' ' << loc.y << ' ' << time << ' ' << step << endl;
  }
};

bool operator<(const pair<int, pos> &p1, const pair<int, pos> &p2) {
  if (p1.first != p2.first) {
    return p1.first < p2.first;
  } else {
    if (p1.second.x == p2.second.x) {
      return p1.second.y < p2.second.y;
    } else {
      return p1.second.x < p2.second.x;
    }
  }
}
bool operator<(const pos &pos1, const pos &pos2) {
  if (pos1.x == pos2.x) {
    return pos1.y < pos2.y;
  } else {
    return pos1.x < pos2.x;
  }
}

bool operator>(const node &node1, const node &node2) {
  return node1.time > node2.time;
};

int main() {
  while (cin >> w >> h) {
    if (!w && !h) {
      break;
    }
    vector<int> starts;
    vector<int> goals;
    map<pos, int> W;
    //壁の情報を得る
    for (int y = h; y > 0; y--) {
      for (int x = 1; x <= w; x++) {
        char s;
        cin >> s;
        if (s == 'S') {
          starts.push_back(x);
          W[{x, y}] = 0;
        } else if (s == 'T') {
          goals.push_back(x);
          W[{x, y}] = 0;
        } else if (s == 'X') {
          W[{x, y}] = INF;
        } else {
          W[{x, y}] = s - '0';
        }
      }
    }

    //それぞれの地点から行ける場所をdestsに入れる
    // step->left:1, right:-1
    // <step, from> : <to, time>
    map<pair<int, pos>, vector<pair<pos, int>>> dests;
    for (int y = 1; y <= h; y++) {
      for (int x = 1; x <= w; x++) {
        if (W[{x, y}] != INF) {
          for (int step : {1, -1}) {
            for (int offset_x = 1; offset_x <= 3; offset_x++) {
              for (int offset_y = offset_x - 3; offset_y <= 3 - offset_x;
                   offset_y++) {
                pos next_pos = {x + step * offset_x, y + offset_y};
                if (!next_pos.is_out() && W[next_pos] != INF) {
                  dests[{step, {x, y}}].push_back({next_pos, W[next_pos]});
                }
              }
            }
          }
        }
      }
    }

    int ans = INF;
    priority_queue<node, vector<node>, greater<node>> pQ;
    // <pos, step> : time
    map<pair<pos, int>, int> tmp;
    map<pair<pos, int>, int> T;
    for (int s : starts) {
      for (int step : {1, -1}) {
        for (int i = 1; i <= w; i++) {
          for (int j = 1; j <= h; j++) {
            tmp[{{i, j}, step}] = INF;
            T[{{i, j}, step}] = INF;
          }
        }
        pQ.push({{s, 1}, 0, step});
        tmp[{{s, 1}, step}] = 0;
      }
    }
    // ダイクストラ法
    while (!pQ.empty()) {
      node smallest = pQ.top();
      pQ.pop();
      if (T[{smallest.loc, smallest.step}] == INF) {
        T[{smallest.loc, smallest.step}] = smallest.time;
        for (pair<pos, int> dest : dests[{smallest.step, smallest.loc}]) {
          if (tmp[{dest.first, smallest.step}] > smallest.time + dest.second) {
            tmp[{dest.first, smallest.step}] = smallest.time + dest.second;
            pQ.push({dest.first, tmp[{dest.first, smallest.step}],
                     smallest.step * -1});
          }
        }
      }
    }
    for (int g : goals) {
      ans = min(ans, T[{{g, h}, 1}]);
      ans = min(ans, T[{{g, h}, -1}]);
    }

    cout << (ans == INF ? -1 : ans) << endl;
  }
}

/*
問題:Cliff
Climbing(http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1150)
所要時間：120m
*/



Measured memory_bytes: 4388