#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
using namespace std;

#define rep(i,n) for((i)=0; (i)<(int)(n); ++(i))
#define foreach(c,itr) for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
typedef long long ll;
typedef pair<ll,int> P;

struct Point {
  int x, y, id;
  Point(){
  }
  Point(int a, int b, int c) : x(a), y(b), id(c) {
  }
};

struct Edge {
  int to, cost;
  Edge(int a, int b) : to(a), cost(b) {
  }
};

int w, h, max_num;
vector<Point> V[2500];
vector<Edge> es[2500];
Point s, g;

const int inf = 1<<28;
ll dp[2500];

int dijkstra(int s, int g) {
  priority_queue<P,vector<P>,greater<P> > q;
  fill(dp, dp + 2500, inf);
  dp[s] = 0;
  q.push(P(0, s));
  
  while (!q.empty()) {
    P p = q.top(); q.pop();
    int v = p.second, i;
    if (dp[v] < p.first) continue;
    //cout << v << "|" << dp[v] << endl;
    rep (i,es[v].size()) {
      Edge te = es[v][i];
      if (dp[te.to] > dp[v] + te.cost) {
        dp[te.to] = dp[v] + te.cost;
        q.push(P(dp[te.to], te.to));
      }
    }
  }
  
  return dp[g];
}

void solve() {
  int i, j, k, id = 1;
  int s_id = 0, g_id;
  max_num = 0;
  string in;
  
  rep (i,h) rep (j,w) {
    cin >> in;
    if (in == ".") continue;
    if (in == "S") {
      s.x = j, s.y = i; continue;
    }
    if (in == "G") {
      g.x = j, g.y = i; continue;
    }
    int num = atoi(in.c_str());
    max_num = max(max_num, num);
    V[num].push_back(Point(j,i,id));
    id++;
  }
  if (max_num != 0) {
    g_id = id;
    // id of S is 0, id of G is @id.
    // connect S & 1
    rep (i,V[1].size()) {
      int dist = abs(s.x - V[1][i].x) + abs(s.y - V[1][i].y);
      es[0].push_back(Edge(V[1][i].id, dist));
    }
    // connect
    for (i = 1; i < max_num; i++) {
      rep (j,V[i].size()) rep (k,V[i+1].size()) {
        int dist = abs(V[i][j].x - V[i+1][k].x) + abs(V[i][j].y - V[i+1][k].y);
        int a_id = V[i][j].id, b_id = V[i+1][k].id;
        es[a_id].push_back(Edge(b_id, dist));
      }
    }
    // connect max_num & G
    rep (i,V[max_num].size()) {
      int dist = abs(g.x - V[max_num][i].x) + abs(g.y - V[max_num][i].y);
      int t_id = V[max_num][i].id;
      es[t_id].push_back(Edge(g_id, dist));
    }
  } else {
    cout << abs(s.x - g.x) + abs(s.y - g.y) << endl;
    return;
  }
    
  
  // dijkstra
  cout << dijkstra(s_id, g_id) << endl;
  
  // clear
  rep (i,max_num+1) V[i].clear();
  rep (i,g_id+1) es[i].clear();
}

int main() {
  while (cin >> w >> h, w|h) {
    solve();
  }
  return 0;
}