Go: ///
// File:  0558.go
// Author: ymiyamoto
//
// Created on Sun Mar  4 20:58:45 2018
//
package main

import (
	"fmt"
	"strconv"
	"strings"
)

type pos struct {
	x, y int
}

var H, W, N int
var graph [][]string

func wfs(p pos, index int) (int, pos) {
	var q []pos
	dists := make([][]int, H)
	for i := range dists {
		dists[i] = make([]int, W)
	}

	q = append(q, p)
	for len(q) > 0 {
		p := q[0]
		dist := dists[p.x][p.y]
		q = q[1:]

		for _, d := range []pos{{-1, 0}, {1, 0}, {0, -1}, {0, 1}} {
			x := p.x + d.x
			y := p.y + d.y
			if 0 <= x && x < H && 0 <= y && y < W && graph[x][y] != "X" && dists[x][y] == 0 {
				dists[x][y] = dist + 1
				q = append(q, pos{x, y})
			}
		}
	}

	for i := range graph {
		for j := range graph[i] {
			if graph[i][j] == strconv.Itoa(index) {
				return dists[i][j], pos{i, j}
			}
		}
	}

	panic("not found")
}

func main() {
	fmt.Scan(&H, &W, &N)

	var start pos

	graph = make([][]string, H)
	for i := range graph {
		var s string
		fmt.Scan(&s)
		graph[i] = strings.Split(s, "")
		for j := range graph[i] {
			if graph[i][j] == "S" {
				start.x = i
				start.y = j
			}
		}
	}

	count := 0
	for i := 1; i <= N; i++ {
		c, s := wfs(start, i)
		start = s
		count += c
	}

	fmt.Println(count)
}

C++: #include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>

#define INF (1e+9)
#define LLINF (1e+18)
#define LL long long

using namespace std;

typedef struct info{
	int nx;
	int ny;
	int cost;
	int target;
	info(int a,int b,int c,int d){
		nx = a;
		ny = b;
		cost = c;
		target = d;
	}
}info;

bool isNumChar(char c){
	if((0 <= c-48)&&(c-48 <= 9))return true;
	return false;
}

int dx[4] = {0,1,0,-1};
int dy[4] = {1,0,-1,0};

int W,H;
int N;

int sx[16] = {0};
int sy[16] = {0};

char field[1024][1024] = {""};
int record[1024][1024][11] = {0};
bool flag[16] = {false};

queue<info> que;


int ans;



int recordReset(){
	for(int i = 0;i < 1024;i++){
		for(int j = 0;j < 1024;j++){
			for(int k = 0;k < 16;k++){
				record[i][j][k] = INF;
			}
		}
	}
}

int bfs(){
	info now(0,0,0,0);
	info next(0,0,0,0);
	for(int i = 0;i < N;i++){
		next = info(sx[i],sy[i],0,i+1);
		que.push(next);
	}

	recordReset();
	while(!que.empty()){
		now = que.front();
		que.pop();
		if(!flag[now.target]){
			//printf("###(%d,%d):::cost<%d>:::target<%d>\n",now.nx,now.ny,now.cost,now.target);
			if(record[now.nx][now.ny][now.target] > now.cost){
				record[now.nx][now.ny][now.target] = now.cost;
				if((sx[now.target] == now.nx)&&(sy[now.target] == now.ny)){
					flag[now.target] = true;
					//printf("###target<%d> completed\n",now.target);
					ans += record[now.nx][now.ny][now.target];
				}
				else{
					switch(field[now.nx][now.ny]){
					case 'X':
						break;
					default:
						for(int i = 0;i < 4;i++){
							next = info(now.nx + dx[i],now.ny + dy[i],now.cost + 1,now.target);
							que.push(next);
						}
						break;
					}
				}
			}
			else{

			}
		}
	}
}


int main (void){
	//while(true){
		scanf("%d%d",&H,&W);
		scanf("%d",&N);
		//if((W == 0)&&(H == 0))break;

		ans = 0;

		//Reset Field
		for(int i = 0;i < 1024;i++){
			for(int j = 0;j < 1024;j++){
				field[j][i] = 'X';
			}
		}

		//Reset Flag
		for(int i = 0;i < 16;i++){
			flag[i] = false;
		}

		//Reading Data
		for(int i = 1;i <= H;i++){
			scanf(" ");
			for(int j = 1;j <= W;j++){
				scanf("%c",&field[j][i]);
				if(isNumChar(field[j][i])){
					sx[field[j][i]-48] = j;
					sy[field[j][i]-48] = i;
					//printf("###<%d>(%d,%d)\n",field[j][i] - 48,sx[field[j][i] - 48],sy[field[j][i] - 48]);

				}
				else if(field[j][i] == 'S'){
					sx[0] = j;
					sy[0] = i;
					//printf("###<S>(%d,%d)\n",j,i);
				}
			}
		}

		//DBG
		/*for(int i = 0;i < N;i++){
			printf("<%d>(%d,%d)\n",i,sx[i],sy[i]);
		}*/

		bfs();

		printf("%d\n",ans);
	//}

	return 0;
}

C++: #include <bits/stdc++.h>

#define rep_(v, f, l) for (int v = (f), v##_ = (l); v < v##_; ++v)
#define rep(v, n) rep_(v, 0, n)
#define lep(v, n) rep_(v, 1, n + 1)
#define rrep_(v, f, l) for (int v = (l), v##_ = (f); v >= v##_; --v)
#define rrep(v, n) rrep_(v, 0, n - 1)
#define rlep(v, n) rrep_(v, 1, n)
#define show_a(a, size) rep(a##_it, size) std::cout << a[a##_it] << " \n"[a##_it == a##_it_ - 1];
#define show_v(v) show_a(v, v.size())
#define eachv(v, i) rep(i, v.size())
#define reachv(v, i) rrep(i, v.size())
#define debug(x) std::cerr << #x << " = " << x << "\n";

using namespace std;

typedef long long int lint;
struct Edge {
    int src, dst, w;
    Edge(int src, int dst, int w) : src(src), dst(dst), w(w) {}
};
bool operator<(const Edge& a, const Edge& b){
    return a.w != b.w ? a.w > b.w : a.src != b.src ? a.src < b.src : a.dst < b.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

static inline int in(){ int x; scanf("%d", &x); return x; }
static inline lint inl(){ lint x; scanf("%lld", &x); return x; }

const int INF = 10000000;

void shortestPath(const Graph &g, int s, vector<int>& dist, vector<int>& prev){
    int n = g.size();
    dist.assign(n, INF);
    dist[s] = 0;
    prev.assign(n, -1);
    priority_queue<Edge> Q;
    for (Q.push(Edge(-2, s, 0)); !Q.empty();){
        Edge e = Q.top();
        Q.pop();
        if (prev[e.dst] != -1) continue;
        prev[e.dst] = e.src;
        eachv(g[e.dst], i){
            int new_dist = e.w + g[e.dst][i].w;
            int dest = g[e.dst][i].dst;
            int source = g[e.dst][i].src;
            if (dist[dest] > new_dist){
                dist[dest] = new_dist;
                Q.push(Edge(source, dest, new_dist));
            }
        }
    }
}

int main()
{
    int h, w, n;
    h = in();
    w = in();
    n = in();
    vector<string> field;
    rep(i, h){
        string s;
        cin >> s;
        field.push_back(s);
    }
    Graph g(h * w);
    vector<int> cheese(n + 1);
    const int dx[] = {1, -1, 0, 0};
    const int dy[] = {0, 0, 1, -1};
    rep(i, h){
        rep(j, w){
            if (isdigit(field[i][j])){
                cheese[field[i][j] - '0'] = i * w + j;
            }
            if (field[i][j] == 'S'){
                cheese[0] = i * w + j;
            }
            if (field[i][j] != 'X'){
                rep(k, 4){
                    int nx, ny;
                    nx = j + dx[k];
                    ny = i + dy[k];
                    if (nx < 0 || nx >= w || ny < 0 || ny >= h) continue;
                    if (field[ny][nx] != 'X') g[i * w + j].push_back(Edge(i * w + j, ny * w + nx, 1));
                }
            }
        }
    }
    int total_time = 0;
    rep(i, n){
        vector<int> dist, prev;
        shortestPath(g, cheese[i], dist, prev);
        total_time += dist[cheese[i + 1]];
    }
    printf("%d\n", total_time);
    return (0);
}