Problem:
11 パズル

太郎君は 8 パズルが大得意で休み時間などにいつも友達に並び替えてもらって遊んでいます。そんなとき、友達から「もっと複雑なパズルは解ける?」と聞かれたのですが、他のパズルはやったことはありません。どうやらその友達は自作で 11 パズルを作っていたみたいです。そのパズルは以下のような形をしています。

11 パズルは 11 枚の正方形のカードと、図 1 のような形の枠を使って行います。最初に 11 枚のカードを枠に入れます。すると 2 カ所の空きスペースができますので、この空きスペースに隣接したカードを動かすことができます。これを繰り返し、カードをきれいに整列して、図 2 の完成型にすることが 11 パズルの目的です。

太郎君はこのパズルに挑戦することにしました。ところが太郎君はこの 11 パズルをいとも簡単に解いてしまいました。そこで友達は「動かす数を一番少なくして解いてよ!」と無茶なことを言ってきました。太郎君は答えがわからないので、プログラムのできるあなたに 11 パズルを解くときの最小ステップ数を出すプログラムを作成してもらってから挑戦することにしました。このとき、2 カ所動かせるところがあるのですが、一つの数字を 1 スペース分移動させることを1ステップとして考えることとします。

11 パズルの初期状態を入力とし、11 パズルを解くときの最小ステップ数を出力するプログラムを作成してください。ただし、パズルを解くときの最小ステップ数が 20 ステップより多くかかってしまう場合は、「NA」と出力してください。パズルの状態は、一行目の情報から順に入力されるものとし、数字の 0 は空きスペースを表します。例えば、図 1 の状態を表す入力は以下のようになります。

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

Input

複数のデータセットの並びが入力として与えられます。入力の終わりは-1ひとつの行で示されます。 各データセットは以下の形式で与えられます。

p1
p2 p3 p4
p5 p6 p7 p8 p9
p10 p11 p12
p13

i 行目にパズルの i 行目の情報 pi (0 ≤ pi ≤ 11) が空白区切りで与えられます。

データセットの数は 100 を超えません。

Output

データセット毎に、最小ステップ数または NA を１行に出力します。

Sample Input

2
1 0 3
4 5 6 7 8
9 0 11
10
0
1 2 3
4 5 6 7 8
9 10 11
0
0
11 10 9
8 7 6 5 4
3 2 1
0
-1

Output for the Sample Input

2
0
NA

Solution in JAVA (judge verdict: Wrong Answer)

import java.util.*;
public class Main {
	int [][] start;
	final int [] xdir = {0,1,0,-1};
	final int [] ydir = {1,0,-1,0};

	public class C {
		int deep;
		StringBuilder data;
		public C(int deep, String data) {
			this.deep = deep;
			this.data = new StringBuilder(data);
		}
	}

	private int[] getIndex(int ind){
		for(int i=0; i < 7; i++){
			for(int j=0; j < 7; j++){
				if(start[i][j] == ind){
					int [] ans = {j,i};
					return ans;
				}
			}
		}
		return null;
	}

	public void doIt(){
		Scanner sc = new Scanner(System.in);
		LinkedList<C> open = new LinkedList<C>();
		HashMap<String,Integer> close = new HashMap<String, Integer>();
		start = new int[7][7];
		for(int i=0; i < 7; i++){
			Arrays.fill(start[i], -1);
		}
		start[1][3] = 0;
		start[2][2] = 1;
		start[2][3] = 2;
		start[2][4] = 3;
		start[3][1] = 4;
		start[3][2] = 5;
		start[3][3] = 6;
		start[3][4] = 7;
		start[3][5] = 8;
		start[4][2] = 9;
		start[4][3] = 10;
		start[4][4] = 11;
		start[5][3] = 12;
		open.addLast(new C(0,"0123456789ab0"));
		close.put("0123456789ab0", 0);

		while(! open.isEmpty()){
			C pat = open.remove();
			StringBuilder patStr = pat.data;
			int patDeep = pat.deep;
			int lastInd = 0;
			if(patDeep >= 10){
				open.clear();
				break;
			}

			for(int i=0; i < 2; i++){
				int ind = patStr.indexOf("0", lastInd);
				int [] result = getIndex(ind);
				int x = result[0];
				int y = result[1];

				for(int j=0; j < 4; j++){
					int patX = x + xdir[j];
					int patY = y + ydir[j];
					if(start[patY][patX] >= 0){
						StringBuilder newStr = new StringBuilder(patStr.toString());
						char change = newStr.charAt(start[patY][patX]);
						newStr.setCharAt(ind, change);
						newStr.setCharAt(start[patY][patX], '0');
						String temp = newStr.toString();

						if((! close.containsKey(temp))){
							open.addLast(new C(patDeep + 1, temp));
							close.put(temp, patDeep+1);
						}
					}
				}
				lastInd = ind + 1;
			}
		}

		while(true){
			int n = sc.nextInt();
			if(n == -1){
				break;
			}
			StringBuilder input = new StringBuilder();
			if(n == 10){
				input.append('a');
			}
			else if(n == 11){
				input.append('b');
			}
			else{
				input.append("" + n);
			}

			for(int i=0; i < 12; i++){
				n = sc.nextInt();
				if(n == 10){
					input.append('a');
				}
				else if(n == 11){
					input.append('b');
				}
				else{
					input.append("" + n);
				}
			}
			String inputStr = input.toString();
//			String inputStr = sc.next();
//			if(inputStr.equals("-1"))
//				break;

			if(close.containsKey(inputStr)){
				System.out.println(close.get(inputStr));
			}
			else{
				open.addLast(new C(0,inputStr));
				HashMap<String,Integer> anotherclose = new HashMap<String, Integer>();
				anotherclose.put(inputStr, 0);
				while(! open.isEmpty()){
					C pat = open.remove();
					StringBuilder patStr = pat.data;
					int patDeep = pat.deep;
					int lastInd = 0;

					if((close.containsKey(patStr.toString()))){
						System.out.println(patDeep + close.get(patStr.toString()));
						break;
					}

					if(patDeep >= 11){
						System.out.println("NA");
						break;
					}

					for(int i=0; i < 2; i++){
						int ind = patStr.indexOf("0", lastInd);
						int [] result = getIndex(ind);
						int x = result[0];
						int y = result[1];

						for(int j=0; j < 4; j++){
							int patX = x + xdir[j];
							int patY = y + ydir[j];
							if(start[patY][patX] >= 0){
								StringBuilder newStr = new StringBuilder(patStr.toString());
								char change = newStr.charAt(start[patY][patX]);
								newStr.setCharAt(ind, change);
								newStr.setCharAt(start[patY][patX], '0');
								String temp = newStr.toString();

								if((! anotherclose.containsKey(temp))){
									open.addLast(new C(patDeep + 1, temp));
									anotherclose.put(temp, patDeep+1);
								}
							}
						}
						lastInd = ind + 1;
					}
				}

			}
		}

	}
	public static void main(String[] args) {
		Main obj = new Main();
		obj.doIt();
	}
}