Language: C++

function main(){
  var i = 0;
  while(true){
    var fieldInfo = input[i].split(' ');
    var width = fieldInfo[0] - 0;//toInt
    var height = fieldInfo[1] - 0;//toInt
            
    // 0 0が入力された
    if(!width && !height){
      break;
    }
            
    var start;
    var goal;
    var elem = [[],[],[],[],[]];
    
    var c;
    for(var y = height; y--;){
      i++;//1行進める
      var ni = input[i];
      for(var x = width; x--;){
        c = ni[x];
    
        if(c === '.'){
          // ドットが一番多いはずなので、先にひっかけてしまう
        }else if(c === '1' || c === '2' || c === '3' || c === '4' || c === '5'){
          // 次に多いはずの属性を潰す
          // FIXME:判定条件は最適化できそう
          var e = elem[c - 1];
          e[e.length] = pos(x, y);
        }else if(c === 'S'){
          start = pos(x, y);
        }else{
          goal = pos(x, y);
        }
            
      }
    }
            
    var INF = 1 << 27;
    var bestElement = -1;
    var distance = INF;
                
    // 属性ごとにループ
    var startElem = 5;
    for (; startElem--;) {
      // DPの初期化 DP[属性][同じ属性内の連番]
      var dp = [[],[],[],[],[]];
      for(var h = 5; h--;){
        var hLength = elem[h].length;
        dp[h].length = hLength;
        var initdph = dp[h];
        for(; hLength--;){
          initdph[hLength] = INF;
        }
      }
                  
      // 最初に選んだパチモンから次に捕まえられる属性番号
      var first = (startElem + 1) % 5;
            
      var firstLength = elem[first].length;
      var dpf = dp[first];
      var elemf = elem[first];
      for (var j = 0; j < firstLength; j++) {
        // s→e1を計算
        dpf[j] = dist(start, elemf[j]);
      }
                  
      // s->1->2->3->4->g
      // なので、ループは間の-> * 3分まわす
      for (var e = 0; e < 3; e++) {
        // ex->e(x+1)
        var now = (first + e) % 5;
        var next = (now + 1) % 5;
        var dpnw = dp[now];
        var dpnx = dp[next];
        var elnw = elem[now];
        var elnx = elem[next];
        var nowLength = elnw.length;
        var nextLength = elnx.length;
        for (var j = 0; j < nowLength; j++) {
          var dpnwj = dpnw[j];
          var elnwj = elnw[j];
          for (var k = 0; k < nextLength; k++) {
            dpnx[k] = min(
              dpnx[k],
              dpnwj + 
                  dist(elnwj, elnx[k]));
          }
        }
      }
                  
      var last = (first + 3) % 5;
      var lastLength = elem[last].length;
      var dpl = dp[last];
      var ell = elem[last];
      for (var j = 0; j < lastLength; j++) {
        // e4->g
        var d = ((dpl[j] + dist(ell[j], goal)) << 3) + startElem;
                    
        distance = min(d, distance);
      }
                  
    }
                
    if (distance === INF) {
      console.log("NA");
    } else {
      console.log(((distance & 7) + 1) + " " + (distance >> 3));
    }
            
    i++;
  }
              
            
}
            
function dist(from, to){
  // x座標とy座標の切り出し(11ビット右シフトでxを、2047(下位10ビット1)とのAND演算でyを取り出す)
  return abs((from >> 11) - (to >> 11)) + abs((from & 2047) - (to & 2047));
}
            
function min(a, b){
  // ビット演算で高速化
  var t = a - b;
 return b + (t & (t >> 31));
}
            
function pos(a, b){
  // 2^10 = 1024なので、下位10ビットでy座標を、上位ビットでx座標を表す
  return (a << 11) + b;
}
           
function abs(a){
 // ビット演算で高速化
 var mask = a >> 31;
 return (a ^ mask) - mask;
}
            
var
input = '';
            
process.stdin.resume();
process.stdin.setEncoding('utf8');
process.stdin.on('data', function(chunk) {
  input += chunk;
});
process.stdin.on('end', function() {
  input = input.split('\n');
  main();
});

Compiler output:
a.cc:141:9: error: empty character constant
  141 | input = '';
      |         ^~
a.cc:144:27: warning: multi-character character constant [-Wmultichar]
  144 | process.stdin.setEncoding('utf8');
      |                           ^~~~~~
a.cc:145:18: warning: multi-character character constant [-Wmultichar]
  145 | process.stdin.on('data', function(chunk) {
      |                  ^~~~~~
a.cc:148:18: warning: multi-character character constant [-Wmultichar]
  148 | process.stdin.on('end', function() {
      |                  ^~~~~
a.cc:1:1: error: 'function' does not name a type; did you mean 'union'?
    1 | function main(){
      | ^~~~~~~~
      | union
a.cc:118:1: error: 'function' does not name a type; did you mean 'union'?
  118 | function dist(from, to){
      | ^~~~~~~~
      | union
a.cc:123:1: error: 'function' does not name a type; did you mean 'union'?
  123 | function min(a, b){
      | ^~~~~~~~
      | union
a.cc:129:1: error: 'function' does not name a type; did you mean 'union'?
  129 | function pos(a, b){
      | ^~~~~~~~
      | union
a.cc:134:1: error: 'function' does not name a type; did you mean 'union'?
  134 | function abs(a){
      | ^~~~~~~~
      | union
a.cc:140:1: error: 'var' does not name a type
  140 | var
      | ^~~
a.cc:143:1: error: 'process' does not name a type
  143 | process.stdin.resume();
      | ^~~~~~~
a.cc:144:1: error: 'process' does not name a type
  144 | process.stdin.setEncoding('utf8');
      | ^~~~~~~
a.cc:145:1: error: 'process' does not name a type
  145 | process.stdin.on('data', function(chunk) {
      | ^~~~~~~
a.cc:147:2: error: expected unqualified-id before ')' token
  147 | });
      |  ^
a.cc:148:1: error: 'process' does not name a type
  148 | process.stdin.on('end', function() {
      | ^~~~~~~
a.cc:151:2: error: expected unqualified-id before ')' token
  151 | });
      |  ^