#include <cstdio>
#include <cstdint>
#include <cctype>
#include <cassert>
#include <vector>
#include <algorithm>
#include <utility>
#include <map>
#include <queue>
#include <tuple>
#include <string>

using zahyo = std::pair<size_t, size_t>;

int const inf = 1e9;
struct graph {
  size_t n;
  std::vector<std::vector<int>> g;
  graph() = default;
  graph(size_t n): g(n, std::vector<int>(n, inf)) {}
  std::vector<int>& operator [](size_t i) { return g[i]; }
  std::vector<int> const& operator [](size_t i) const { return g[i]; }
};

constexpr size_t m1 = -1;
constexpr size_t di[] = {m1, 0, 1, 0};
constexpr size_t dj[] = {0, m1, 0, 1};

std::vector<std::vector<int>> neko(std::vector<std::string> const& s,
				   size_t si, size_t sj) {

  size_t h = s.size();
  size_t w = s[0].size();
  std::vector<std::vector<int>> res(h, std::vector<int>(w, inf));
  res[si][sj] = 0;
  std::queue<zahyo> q;
  q.emplace(si, sj);
  while (!q.empty()) {
    size_t i, j;
    std::tie(i, j) = q.front();
    q.pop();
    for (int k = 0; k < 4; ++k) {
      size_t ni = i + di[k];
      size_t nj = j + dj[k];
      if (!(ni < h && nj < w)) continue;
      if (!(res[ni][nj] > res[i][j] + 1)) continue;
      if (s[ni][nj] == '#') continue;
      res[ni][nj] = res[i][j] + 1;
      size_t nc = s[ni][nj];
      if (isalpha(nc) && (nc != 'S' && nc != 'T')) continue;
      q.emplace(ni, nj);
    }
  }
  return res;
}

size_t enc(char c) {
  if (c == 'S') return 30;
  if (c == 'T') return 31;
  if (isdigit(c)) return c-'0';
  if (islower(c)) return c-'a'+10;
  if (isupper(c)) return c-'A'+20;
  assert(false);
}

int main() {
  size_t W, H;
  scanf("%zu %zu", &W, &H);

  std::vector<std::string> s(H);
  std::map<char, zahyo> map;
  for (size_t i = 0; i < 10; ++i) {
    map['0'+i] = zahyo(-1, -1);
    map['a'+i] = zahyo(-1, -1);
    map['A'+i] = zahyo(-1, -1);
  }

  for (size_t i = 0; i < H; ++i) {
    char buf[1024];
    scanf("%s", buf);
    s[i] = buf;
    for (size_t j = 0; j < W; ++j)
      if (isalnum(s[i][j])) map[s[i][j]] = zahyo(i, j);
  }

  std::vector<std::vector<int>> a(10, std::vector<int>(10));
  for (auto& ai: a)
    for (auto& aij: ai)
      scanf("%d", &aij);

  graph g(32);
  for (auto const& p: map) {
    char sc = p.first;
    size_t si, sj;
    std::tie(si, sj) = p.second;
    if (si+1 == 0) continue;
    auto dist = neko(s, si, sj);
    for (auto const& p1: map) {
      char gc = p1.first;
      size_t gi, gj;
      std::tie(gi, gj) = p1.second;
      if (gi+1 == 0) continue;
      g[enc(sc)][enc(gc)] = dist[gi][gj];
      // fprintf(stderr, "%c -> %c: %d\n", sc, gc, dist[gi][gj]);
    }
  }

  std::vector<graph> gs(1<<10, graph(22));
  for (size_t i = 0; i < gs.size(); ++i) {
    std::vector<int> use;
    use.push_back('S');
    for (int j = '0'; j <= '9'; ++j) use.push_back(j);
    use.push_back('T');
    for (int j = 0; j < 10; ++j) {
      int cj = 'A'+j;
      if (i >> j & 1) cj = tolower(cj);
      use.push_back(cj);
    }
    for (size_t j = 0; j < use.size(); ++j)
      for (size_t k = 0; k < use.size(); ++k)
	gs[i][j][k] = g[enc(use[j])][enc(use[k])];

    size_t M = use.size();
    for (size_t m = 0; m < M; ++m)
      for (size_t j = 0; j < M; ++j)
	for (size_t k = 0; k < M; ++k)
	  gs[i][j][k] = std::min(gs[i][j][k], gs[i][j][m]+gs[i][m][k]);

    // if (i == 0 || i+1 == gs.size()) {
    //   fprintf(stderr, "=== %zu ===\n", i);
    //   for (size_t j = 0; j < use.size(); ++j) fprintf(stderr, "%2c%c", use[j], j+1<use.size()? ' ': '\n');
    //   for (size_t j = 0; j < 22; ++j)
    //     for (size_t k = 0; k < 22; ++k)
    //       fprintf(stderr, "%2d%c", gs[i][j][k], k<21? ' ': '\n');
    // }
  }

  using res_type = std::pair<int, int>;  // (step, -score)
  std::vector<std::vector<res_type>> dp(1<<10, std::vector<res_type>(12, res_type(inf, -inf)));
  dp[0][0] = res_type(0, 0);
  for (size_t i = 0; i < (1<<10); ++i) {
    for (size_t j = 0; j < 11; ++j) {
      if (!(j == 0 || (i >> (j-1) & 1))) continue;
      for (size_t k = 1; k < 11; ++k) {
	if (i >> (k-1) & 1) continue;
	size_t ni = i | 1 << (k-1);
	int step = dp[i][j].first + gs[i][j][k];
	if (step > inf) continue;
	int score = dp[i][j].second;
	if (j > 0) {
	  score -= a[j-1][k-1];
	}
	res_type next(step, score);
	dp[ni][k] = std::min(dp[ni][k], next);
      }
    }
  }

  res_type res(inf, inf);
  for (size_t j = 1; j < 11; ++j) {
    int step = dp.back()[j].first + gs.back()[j][11];
    int score = dp.back()[j].second;
    res_type next(step, score);
    res = std::min(res, next);
  }
  if (res.first == inf) return puts("-1"), 0;
  printf("%d %d\n", res.first, -res.second);
}



Measured memory_bytes: 7564