Problem:
Problem D: 伝説の剣

※ この問題には厨二成分が多く含まれます。胸焼けにご注意ください。

ついに復活を遂げた魔王は、再び世界を闇に包むために人間界に攻め入ろうとしていた。

魔王は、本格的な侵攻を始める前に、まず伝説の剣を破壊することにした。
前回の戦争において、魔王は伝説の剣を持つ勇者によって倒された。
魔王の体は闇の衣によって守られているため、生半可な攻撃では魔王を傷つけることはできない。
しかし、伝説の剣は、神々の加護により、魔王の闇の衣すら容易に貫いてしまう。
そのため、今回の戦争に勝利するためには、なんとしてもその伝説の剣を手に入れて破壊する必要がある。

調査の末、伝説の剣はとある遺跡の最奥に安置され、次代の勇者が現われるのを待っていることがわかった。
伝説の剣は、邪悪な者や盗賊によって奪われるのを防ぐために、周囲に点在する無数の宝珠によって封印されている。
魔王は、強力な魔力を持っているため、触れるだけで宝珠を破壊することができる。
ただし、宝珠による封印は多重構造になっており、表層から順に破壊していく必要がある。
例えば、第1の封印の宝珠を破壊する前に第2以降の封印の宝珠に触れたとしても、破壊することはできない。
また、複数の宝珠が同じ封印を構成していることもあるが、魔王はそのうちの一つに触れるだけで、同時にその封印を破壊することができる。

遺跡には神聖な力が満ちており、並の魔物では入ることすらままならない。
そこで、魔王自ら赴き伝説の剣を回収してくることになった。
いかに魔王といえど、長時間その力を受け続ければただではすまない。
魔王の右腕であるあなたの仕事は、念のため魔王が全ての封印を破壊し、伝説の剣の下に辿りつくまでの時間を求めることである。

Input

入力は、複数のデータセットからなり、入力の終わりはスペースで区切られたゼロ二つからなる行である。
データセットの総数は50以下である。
各データセットは、次の形式をしている。

w h
s(1,1) ... s(1,w)
s(2,1) ... s(2,w)
...
s(h,1) ... s(h,w)

wとhは、それぞれ遺跡のフロアを表現する行列データの幅と高さを示す整数であり、それぞれ1 ≤ w, h ≤ 100であり、2 ≤ w + h ≤ 100と仮定して良い。
続くh行はそれぞれ、スペースで区切られたw個の文字から構成されており、文字s(y,x)は、座標(y,x)の地点の状態を示す。

その意味は、以下の通りである。

S：魔王が最初にいる地点。フロアに必ず1つだけ存在する。

G：伝説の剣の地点。必ず1つだけ存在する。

.：なにもない。

数字：宝珠がある地点。数字は構成する封印の番号を示す。数字は1以上の整数であり、間の数字に抜けはないとしてよい。

また、魔王は、遺跡のフロア内の上下左右の隣接する座標に移動することができ、その移動にかかる時間を1とする。
破壊できる宝珠は触れるだけで破壊できるため、宝珠の破壊には時間はかからない。

Output

各データセットに対して、魔王が全ての封印を破壊し、伝説に剣に辿りつくために必要な最短時間を出力せよ。

Sample Input

10 10
S . . . . . . . . .
. . . . . . . . . .
. . . . 1 . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . 3 . .
. . . . . . . . . .
. . . . . 4 . . . .
. . . . . . . . . .
2 . . . . . . . . G
10 10
S . . . . . 3 . . .
. . 3 . . . . . . .
. . . . 1 . . . . .
. . . . . . 4 . . .
. . 3 . . . 1 . . .
. . . . . . . 3 . .
. . . . . . . . . .
. . . . . 4 . . . .
. . . . . 5 . . . .
2 . . . . . . . . G
10 10
S . . . . . . . . 1
. . . . . 5 . . . .
. 4 . . . . . . . .
. . . . 8 . 9 . . .
. . . . 10 . . . . .
. . 7 . G . . . . .
. . . 11 . . . . . .
3 . . . . . . . . 6
. . . . . . . 2 . .
. . . . . . . . . .
0 0

Output for Sample Input

38
36
71

Solution in C++11 (judge verdict: Accepted)

#include <bits/stdc++.h>

using namespace std;

#define LOG(...) fprintf(stderr,__VA_ARGS__)
//#define LOG(...)
#define FOR(i,a,b) for(int i=(int)(a);i<(int)(b);++i)
#define REP(i,n) for(int i=0;i<(int)(n);++i)
#define ALL(a) (a).begin(),(a).end()
#define RALL(a) (a).rbegin(),(a).rend()
#define EXIST(s,e) ((s).find(e)!=(s).end())
#define SORT(c) sort(ALL(c))
#define RSORT(c) sort(RALL(c))

typedef long long ll;
typedef unsigned long long ull;
typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<vb> vvb;
typedef vector<vi> vvi;
typedef vector<vll> vvll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

#define INF 1e9

int W, H;

int main() {
    while (cin >> W >> H, W|H) {
        vvi field(H, vi(W, -1));
        int goal = 0;
        REP(y, H) REP(x, W) {
            string s;
            cin >> s;
            if (s == ".") {
            } else if (s == "S") {
                field[y][x] = 0;
            } else if (s == "G") {
                field[y][x] = -2;
            } else {
                int n = stoi(s);
                field[y][x] = n;
                goal = max(goal, n);
            }
        }
        goal++;
        vector<vector<pii>> treasure(goal+1);
        REP(y, H) REP(x, W) {
            if (field[y][x] == -2) {
                field[y][x] = goal;
            }
            int n = field[y][x];
            if (n >= 0) {
                treasure[n].push_back({x, y});
            }
        }

        vvi dp(H, vi(W, INF));
        int x = treasure[0][0].first, y = treasure[0][0].second;
        dp[y][x] = 0;
        FOR(i, 1, goal+1) {
            for (pii from : treasure[i-1]) {
                int x1 = from.first, y1 = from.second;
                for (pii to : treasure[i]) {
                    int x2 = to.first, y2 = to.second;
                    int step = abs(x1-x2) + abs(y1-y2);
                    dp[y2][x2] = min(dp[y2][x2], dp[y1][x1] + step);
                }
            }
        }
        int gx = treasure[goal][0].first, gy = treasure[goal][0].second;
        cout << dp[gy][gx] << endl;
    }
}