#include <bits/stdc++.h>
#define rep(i,n) for (int i = 0; i < (int)(n); i++)
#define REP(i,n) for (int i = 1; i < (int)(n); i++)
#define all(x) x.begin(),x.end()
#define rall(x) x.rbegin(),x.rend()
#define debug(var) do{cout << #var << " : "; view(var);}while(0)
template<class T> bool chmin(T &a, T b) {if(a>b) {a=b;return 1;}return 0;}
template<class T> bool chmax(T &a, T b) {if(a<b) {a=b;return 1;}return 0;}
using namespace std;
template<class T> void view(T e) {cout << e << endl;}
template<class T> void view(const vector<T> &v) {for(const auto &e : v){cout << e << " ";} cout << endl;}
template<class T> void view(const vector<vector<T>> &vv) {for(const auto &v : vv){view(v);}}
using vint = vector<int>;
using vvint = vector<vector<int>>;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vector<ll>>;
using P = pair<int,int>;
const int inf = 1<<30;
const ll inf_l = 1LL<<61;
const int MAX = 1e5;

vint dx = {1, 0, -1, 0};
vint dy = {0, 1, 0, -1};

int h, w;
vector<string> field;
P start, goal;
int d[2005][2005];
vector<vector<P>> warp(26);

int to_int(P p) {
    return p.first * w + p.second;
}

P to_cood(int x) {
    return P(x / w, x % w);
}

void solve(P p) {
    priority_queue<P, vector<P>, greater<P>> q;
    q.push(P(0, to_int(p)));
    while (!q.empty()) {
        P p = q.top(); q.pop();
        int x = to_cood(p.second).second;
        int y = to_cood(p.second).first;
        if (d[y][x] < p.first) continue;
        d[y][x] = p.first;
        if ('a' <= field[y][x] && field[y][x] <= 'z') {
            vector<P> &w = warp[field[y][x] - 'a'];
            auto ptr = w.begin();
            while (ptr != w.end()) {
                if (d[(*ptr).first][(*ptr).second] > p.first + 1) {
                    d[(*ptr).first][(*ptr).second] = p.first + 1;
                    q.push(P(p.first + 1, to_int(*ptr)));
                    ptr++;
                } else ptr = w.erase(ptr);
            }
        }
        rep(i,4) {
            int n_x = x + dx[i];
            int n_y = y + dy[i];
            if (n_x >= 0 && n_x < w && n_y >= 0 && n_y < h) {
                if (field[n_y][n_x] == '#') continue;
                if (d[n_y][n_x] > p.first + 1) {
                    d[n_y][n_x] = p.first + 1;
                    q.push(P(p.first + 1, to_int(P(n_y, n_x))));
                }
            }
        }
    }
}

int main() {
    cin >> h >> w;
    field.resize(h);
    rep(i,h) cin >> field[i];
    rep(i,h)rep(j,w) {
        if (field[i][j] == 'S') start = P(i, j);
        if (field[i][j] == 'G') goal = P(i, j);
        if ('a' <= field[i][j] && field[i][j] <= 'z') {
            warp[field[i][j] - 'a'].push_back(P(i, j));
        }
    }
    rep(i,h)rep(j,w) d[i][j] = inf;
    solve(start);
    // rep(i,h) {
    //     rep(j,w) cout << d[i][j] << " ";
    //     cout << endl;
    // }
    int ans = d[goal.first][goal.second];
    if (ans == inf) cout << -1 << endl;
    else cout << ans << endl;
}
#include <bits/stdc++.h>
#include <math.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rep2(i, s, n) for (int i = (s); i < (int)(n); i++)
using ll = long long;
using vec = vector<ll>;
using vec2 = vector<vector<ll>>;
const ll inf = 1e18;
const ll mod = 1e9 + 7;

int main(){
  ll h, w;
  cin >> h >> w;
  vector<vector<char>> A(h,vector<char>(w));
  rep(i,h){
    rep(j,w){
      cin >> A[i][j];
    }
  }

  //yoko
  ll ans = 0;
  for(int i = 0;i < h;i++){
    for(int j = 0;j <= w-2;j++){
      if(A[i][j] == '.' && A[i][j+1] == '.'){
        ans++;
      }
    }
  }
  for(int i = 0;i <= h-2;i++){
    for(int j = 0;j < w;j++){
      if(A[i][j] == '.' && A[i+1][j] == '.'){
        ans++;
      }
    }
  }
  cout << ans << endl;

}