#include<bits/stdc++.h>
using namespace std;
using Int = long long;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}

//INSERT ABOVE HERE
const int VS = 32;
const int DS = 10;
const int MAX = 1010;
int d[DS+1][DS+1]; // input
int dist[VS][VS];  // compress graph
int dp1[MAX][MAX]; // for BFS
int dp2[DS+1][VS][1<<DS];// for shortest path
int dp3[DS+1][VS][1<<DS];// for maximum value

signed main(){

  int w,h;
  cin>>w>>h;
  vector<string> s(h);
  for(int i=0;i<h;i++) cin>>s[i];

  memset(d,0,sizeof(d));
  for(int i=0;i<DS;i++)
    for(int j=0;j<DS;j++)
      cin>>d[i][j];
  
  const int INF = 1e9;
  for(int i=0;i<VS;i++)
    for(int j=0;j<VS;j++)
      dist[i][j]=INF;

  auto idx=[&](char c){
             if(c=='S') return 30;
             if(c=='T') return 31;
             if(isdigit(c)) return c-'0';
             if(isupper(c)) return c-'A'+10;
             if(islower(c)) return c-'a'+20;
             return -1;
           };
  
  auto in=[&](int y,int x){return 0<=y&&y<h&&0<=x&&x<w;};

  // move in only '.'
  auto bfs=
    [&](int y,int x){
      int v=idx(s[y][x]);
      if(v<0) return;
      memset(dp1,-1,sizeof(dp1));

      using P = pair<int, int>;
      queue<P> q;
      int dy[]={0,0,1,-1};
      int dx[]={1,-1,0,0};
      dp1[y][x]=0;
      q.emplace(y,x);

      while(!q.empty()){
        tie(y,x)=q.front();q.pop();
        if(dp1[y][x]&&~idx(s[y][x])) continue;
        for(int k=0;k<4;k++){
          int ny=y+dy[k],nx=x+dx[k];
          if(!in(ny,nx)||s[ny][nx]=='#') continue;
          if(~dp1[ny][nx]) continue;
          dp1[ny][nx]=dp1[y][x]+1;
          q.emplace(ny,nx);
        }
      }
      
      for(int i=0;i<h;i++)
        for(int j=0;j<w;j++)
          if(~idx(s[i][j])&&~dp1[i][j])
            dist[v][idx(s[i][j])]=dp1[i][j];
    };
  
  for(int i=0;i<h;i++)
    for(int j=0;j<w;j++)
      bfs(i,j);
      
  for(int b=0;b<(1<<DS);b++)
    for(int p=0;p<=DS;p++)
      for(int v=0;v<VS;v++)
        dp2[p][v][b]=INF,dp3[p][v][b]=-INF;

  using T = tuple<int, int, int, int>;
  priority_queue<T, vector<T>, greater<T> > pq;
  dp2[DS][idx('S')][0]=0;
  dp3[DS][idx('S')][0]=0;
  pq.emplace(0,DS,idx('S'),0);

  while(!pq.empty()){
    int z,p,v,b;
    tie(z,p,v,b)=pq.top();pq.pop();
    if(dp2[p][v][b]<z) continue;

    auto check=
      [&](int p,int v,int b,int np,int u,int nb){
        int nz=z+dist[v][u];
        if(dp2[np][u][nb]>nz){
          dp2[np][u][nb]=nz;
          dp3[np][u][nb]=-INF;
          pq.emplace(dp2[np][u][nb],np,u,nb);
        }
        if(dp2[np][u][nb]==nz) chmax(dp3[np][u][nb],dp3[p][v][b]+d[p][np]);    
      };
    
    // 0-9(take) 
    for(int u=0;u<10;u++){
      if((b>>u)&1) continue;
      int np=u,nb=b|(1<<u);
      check(p,v,b,np,u,nb);
    }
    
    // 0-9(pass), A-J, a-j, S, T
    for(int u=0;u<32;u++){
      if(10<=u&&u<20&&(( b>>(u-10))&1)) continue;
      if(20<=u&&u<30&&((~b>>(u-20))&1)) continue;
      int np=p,nb=b;      
      check(p,v,b,np,u,nb);
    }
  }

  int di=INF,val=-INF;
  for(int p=0;p<DS;p++){
    if(di>dp2[p][idx('T')][(1<<DS)-1]){
      di=dp2[p][idx('T')][(1<<DS)-1];
      val=-INF;
    }
    if(di==dp2[p][idx('T')][(1<<DS)-1])
      chmax(val,dp3[p][idx('T')][(1<<DS)-1]);
  }
  
  if(di==INF) cout<<-1<<endl;
  else cout<<di<<" "<<val<<endl;
  return 0;
}



Measured memory_bytes: 11636