Language: Java

import java.awt.Point;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class Pachimon {

	/** ????§??????? */
	static final String WHITE_SPACE = " ";

	/** ??????????????????_X */
	static int mapSizeX = 0;

	/** ??????????????????_Y */
	static int mapSizeY = 0;

	/** ??????????????° */
	static int maxNode = 0;

	/** ????????¢??????????????? */
	static List<Point> pachimonList = new ArrayList<Point>();

	/**
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		InputStreamReader is = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(is);

		while (true) {
			String[] mapSizeLine = br.readLine().split(WHITE_SPACE);
			mapSizeX = Integer.parseInt(mapSizeLine[0]);
			mapSizeY = Integer.parseInt(mapSizeLine[1]);
			if (mapSizeX == 0 && mapSizeY == 0)
				break;

			readMap(br);
			Point output = createPos(0, Integer.MAX_VALUE);
			if (maxNode > 5) {
				for (int type = 1; type <= 5; type++) {
					// ??????????????????????????¢??????????????????????????????????????????????´¢
					int cost = searchRoute(type);
					if (cost < output.y && cost > 0) {
						output.x = type;
						output.y = cost;
					}
				}
			}

			// ???????????????
			if (output.y == Integer.MAX_VALUE) {
				System.out.println("NA");
			} else {
				System.out.println(output.x + WHITE_SPACE + output.y);
			}
		}
	}

	/**
	 * ?????????????????????????????????
	 * @param scanner ????????£??????
	 * @throws IOException
	 */
	private static void readMap(BufferedReader br) throws IOException {
		// ??????????????±????????????
		pachimonList.removeAll(pachimonList);
		maxNode = 0;

		for (int i = 0; i < mapSizeY; i++) {
			for (int j = 0; j < mapSizeX; j++) {
				int val = convertInt(br.read());
				if (val < 9) {
					// ???????????¢????????°????¨????
					pachimonList.add(createPos(val, calcIndex(j, i)));
				}
			}
			// ????????????????£???°???
			br.readLine();
		}
		maxNode = pachimonList.size();
	}

	/**
	 * ??¢????????????????????????int??????????????????
	 * @param target ????±??????????
	 * @return ???????????????
	 */
	private static int convertInt(int target) {
		if (target == 83)
			return 0;
		if (target == 71)
			return 6;
		if (target >= 49 && target <= 53)
			return target - 48;
		return 9;
	}

	/**
	 * X????????????????????´?????????????????¢???????±???§????¨????<br>
	 * ????????????:0?????´??????:6???????????¢???????±???§:1???5<br>
	 * Y????????????????????????????????????????´?
	 * @param type ?????????????????´?????????????????¢???????±???§
	 * @param index ??????????????????????????????
	 * @return
	 */
	private static Point createPos(int type, int index) {
		return new Point(type, index);
	}

	/**
	 * ?????¨????????¢???????????????????????????????????????????????¢???????±???§?????????
	 * @param currentType ??????????????????????????¢???????±???§
	 * @return ?????????????????????????????¢???????±???§
	 */
	private static int getNextType(int currentType) {
		if (currentType == 5)
			return 1;
		return currentType + 1;
	}

	/**
	 * ??????????????????????????¢?????????????????????????????????????????¢???????±???§?????????
	 * @param firstType ??????????????????????????¢???????±???§
	 * @return ?????????????????????????????¢???????±???§
	 */
	private static int getEndType(int firstType) {
		if (firstType == 1)
			return 5;
		return firstType - 1;
	}

	/**
	 * ??£??\??????????¨?????????????????????????????????´???????????§???<br>
	 * ????????????????????????????±???????
	 * @param adjacent ??£??\??????
	 * @return ????????????????????????
	 */
	private static int searchRoute(int firstType) {

		/** ?????????????¨??????????????????????????´??????? */
		boolean[] visited = new boolean[maxNode];

		/** ??????????????????????????? */
		int[] cost = new int[maxNode];

		for (int i = 0; i < maxNode; i++) {
			cost[i] = Integer.MAX_VALUE;
			visited[i] = false;
		}

		// ??????????????°????????§???????????????0
		cost[0] = 0;

		while (true) {
			// ?¨?????????????????????????????????§?????????????????????????±???????
			int node = minIndex(cost, visited);
			if (node < 0) {
				return cost[maxNode - 1];
			}
			// ??¢?´¢???????????????????????????????????°????????????
			visited[node] = true;
			for (int j = 0; j < maxNode; j++) {
				if (isLinked(node, j, firstType) && !visited[j]) {
					int nextNodeCost = cost[node] + clucCost(pachimonList.get(node), pachimonList.get(j));
					// ????????§????????¢??????????°????????????°???????????¢??¨???????¨???¶
					if (nextNodeCost < cost[j]) {
						cost[j] = nextNodeCost;
					}
				}
			}
		}
	}

	/**
	 * ?????¨??????????????¨????±??????????????????\?¶?????????????????????????????????\
	 * @param node ?????¨????????????
	 * @param target ????±?????????????
	 * @return ?????\??????
	 */
	private static boolean isLinked(int node, int target, int firstType) {
		int currentType = pachimonList.get(node).x;
		int targetType = pachimonList.get(target).x;
		// ??????????????¢?????¨???????±???§?????????????????????????????????????????\?¶????????????????
		if (currentType == firstType)
			return false;
		// ????±??????????????????¢?????¨???????±???§?????´????????\?¶????????????????
		if (targetType == firstType)
			return false;
		// ??????????????´???????????´????????\?¶??????????????????????????????????
		if (currentType == maxNode)
			return false;

		// ????????????????????????("0")?????´??????????±???????????????????????????¢???????±???§????¬?????????\?¶????????????????
		if (currentType == 0)
			return targetType == getNextType(firstType);

		// ?????¨????????????????±???§????????????????????????????????¢????????´????????´??????????????\?¶?
		if (currentType == getEndType(firstType))
			return targetType == 6;

		return getNextType(currentType) == targetType;
	}

	/**
	 * ?¨???????????????????????????????????????????????????????????????????????????????????±???????
	 * @param cost ???????????????????????????
	 * @param visited ?????????????¨??????????????????????????´???????
	 * @return ??????????????????
	 */
	private static int minIndex(int[] cost, boolean[] visited) {
		int index = 0;
		for (; index < maxNode; index++) {
			if (!visited[index])
				break;
		}
		if (index == maxNode)
			return -1;
		for (int i = index + 1; i < maxNode; i++) {
			if (!visited[i] && cost[i] < cost[index])
				index = i;
		}
		return index;
	}

	/**
	 * ????????????????????????????????´???????????§????????????????¨?????????????
	 * @param sx ???????????????X??§?¨?
	 * @param sy ???????????????Y??§?¨?
	 * @param gx ??´?????????X??§?¨?
	 * @param gy ??´?????????Y??§?¨?
	 * @param nextType ?¬????????????????????????¢????±???§
	 */
	private static int clucCost(Point from, Point to) {
		int fx = from.y / mapSizeY;
		int fy = from.y % mapSizeY;
		int tx = to.y / mapSizeY;
		int ty = to.y % mapSizeY;
		return Math.abs(tx - fx) + Math.abs(ty - fy);
	}

	/**
	 * X??§?¨???¨Y??§?¨???????????????£?????????????????????????????????????????´?????????
	 *
	 * @param x X??§?¨?
	 * @param y Y??§?¨?
	 * @return
	 */
	private static int calcIndex(int x, int y) {
		return x * mapSizeY + y;
	}
}

Compiler output:
Main.java:8: error: class Pachimon is public, should be declared in a file named Pachimon.java
public class Pachimon {
       ^
1 error