#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<vector>
#include<map>
#include<cassert>
#include<iomanip>
#include<queue>
#include<set>
#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define inf (1<<28)
#define MAX 100
#define MAX2 2510
using namespace std;
/*
struct P
{
  int x,y,cost;
  P(int x=-1,int y=-1,int cost=-inf):x(x),y(y),cost(cost){}
};
*/

int h,w;
//string G[MAX][MAX];
//int mincost[MAX2][MAX2];
vector<int> vec[MAX2];
int dp[MAX2];
//int Index[MAX2];
int dx[] = {0,1,0,-1};
int dy[] = {1,0,-1,0};

int getManhattan(int a,int b)
{
  int x1 = a%w;
  int y1 = a/w;
  int x2 = b%w;
  int y2 = b/w; 
  return abs(x1-x2) + abs(y1-y2);
}

int main()
{
  while(cin >> w >> h,w|h)
    {
      //vector<int> ps;
      //rep(i,MAX2)rep(j,MAX2)mincost[i][j] = inf;
      rep(i,MAX2)
	{
	  //Index[i] = -inf;
	  dp[i] = inf;
	  vec[i].clear(); 
	}
      int max_digit = -inf;
      //int index = 0;
      int g;
      rep(i,h)
	{
	  rep(j,w)
	    {
	      string s;
	      cin >> s;
	      if(s[0] == '.')continue;
	      if(s[0] == 'S')
		{
		  //ps.push_back(index);
		  //Index[j+i*w] = index++;
		  vec[0].push_back(j+i*w);
		  dp[j+i*w] = 0;
		}
	      else if(s[0] == 'G')
		{
		  g = j+i*w;	  
		}
	      else
		{
		  //Index[j+i*w] = index;
		  //ps.push_back(index++);
		  int intValue = (atoi)(s.c_str());
		  assert(intValue < MAX2);
		  vec[intValue].push_back(j+i*w);
		  max_digit = max(max_digit,intValue);
		}
	    }
	}

      //Index[g] = index;
      //ps.push_back(index++);
      if(max_digit == -inf)max_digit = 0;
      vec[++max_digit].push_back(g);

      /*
      rep(i,max_digit-1)
	{
	  rep(j,vec[i].size())
	    {
	      int x = vec[i][j]%w;
	      int y = vec[i][j]/w;
	      queue<P> que;
	      que.push(P(x,y,0));
	      mincost[vec[i][j]][vec[i][j]] = 0;
	      while(!que.empty())
		{
		  P p = que.front(); que.pop();

		  rep(k,4)
		    {
		      int nx = p.x + dx[k];
		      int ny = p.y + dy[k];
		      if(!(0 <= nx && nx < w && 0 <= ny && ny < h))continue;
		      if(mincost[vec[i][j]][nx+ny*w] > p.cost + 1)
			{
			  mincost[vec[i][j]][nx+ny*w] = p.cost + 1;
			  que.push(P(nx,ny,p.cost+1));
			}
		    }
		}
	    }
	}
*/
    

      rep(i,max_digit)
	{
	  rep(j,vec[i].size())
	    {
	      //cout << "now : " << vec[i][j] << " (" << vec[i][j]%w << "," << vec[i][j]/w << ")" << endl;
	      if(dp[vec[i][j]] == inf)continue;
	      rep(k,vec[i+1].size())
		{
		  dp[vec[i+1][k]] = min(dp[vec[i+1][k]],
					dp[vec[i  ][j]]+getManhattan(vec[i][j],vec[i+1][k])/*mincost[vec[i][j]][vec[i+1][k]]*/);
		}
	    }
	}
      assert(max_digit < MAX2);
      assert(vec[max_digit][0] < MAX2);
      cout << dp[vec[max_digit][0]] << endl;
    }
  return 0;
}