Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

8 Puzzle

The goal of the 8 puzzle problem is to complete pieces on $3 \times 3$ cells where one of the cells is empty space.

In this problem, the space is represented by 0 and pieces are represented by integers from 1 to 8 as shown below.

1 3 0
4 2 5
7 8 6

You can move a piece toward the empty space at one step. Your goal is to make the pieces the following configuration in the shortest move (fewest steps).

1 2 3
4 5 6
7 8 0

Write a program which reads an initial state of the puzzle and prints the fewest steps to solve the puzzle.

Input

The $3 \times 3$ integers denoting the pieces or space are given.

Output

Print the fewest steps in a line.

Constraints

There is a solution.

Sample Input

1 3 0
4 2 5
7 8 6

Sample Output

4

Solution in JAVA (judge verdict: Accepted)


import java.util.*;
import java.io.*;

class field{
	int cell[] = new int[9];
	int evaluation;
	int route[];
	int floor;

	field(int cell[], int hash){
		floor = 1;
		route = new int[1];
		route[0] = hash;
		for(int i = 0; i < 9; i++) this.cell[i] = cell[i];
		int eva = 0;
		for(int i = 0; i < 9; i++){
			if(cell[i] != 0){
				//?¨???????????????¢?????????
				//i???????????????????????????
				//cell[i]???????????????????????°???
				eva += Math.abs((cell[i]-1)%3 - i%3);
				//?????????????????¢?????????
				eva += Math.abs((cell[i]-1)/3 - i/3);
			}
		}
		evaluation = eva;
	}

	/**/

	field(int cell[], int route[], int hash){
		this.floor = route.length;
		this.route = new int[floor+1];
		System.arraycopy(route, 0, this.route, 0, floor);
		this.route[floor] = hash; //hash???????´???????
		for(int i = 0; i < 9; i++) this.cell[i] = cell[i];
		int eva = 0;
		for(int i = 0; i < 9; i++){
			if(cell[i] != 0){
				//?¨???????????????¢?????????
				//i???????????????????????????
				//cell[i]???????????????????????°???
				eva += Math.abs((cell[i]-1)%3 - i%3);
				//?????????????????¢?????????
				eva += Math.abs((cell[i]-1)/3 - i/3);
			}
		}
		evaluation = eva; //??¨????????????
	}

	public String toString(){
		return new String(cell[0] + " " + cell[1] + " " + cell[2] + "\n" + cell[3] + " " + cell[4] + " " + cell[5] + "\n" + cell[6] + " " + cell[7] + " " + cell[8] + "\n");
	}
}

/**/
class ev_list{
	field elem;
	ev_list next;
	
	ev_list(){
		next = null;
		this.elem = null;
	}

	ev_list(field elem){
		next = null;
		this.elem = elem;
	}

	/**/
	public void insert(ev_list node){
		//?????\??????????????£????????¢??°??????????¬???????????????????????????§?????????
		//??????????¬???????????????????????????¨????????\
		if(this.next == null || this.next.elem.evaluation + this.next.elem.floor < node.elem.evaluation + node.elem.floor){
			//?¬????????????????????????\??????????????£????????¢??°??????????°??????????
			//this, this.next???node????????\??????this, node, node.next(this.next)?????????
			node.next = this.next;
			this.next = node;
		}else this.next.insert(node);
		//?¬????????????????????????????????????§????????¨???????¬????????????????node????????\??????
	}

	/**/
	public field pop(){
		if(this.next == null) return null;
		if(this.next.next == null){ //?¬?????¬????null??????
			field temp = this.next.elem; //???????¬?????????£????????????temp???
			this.next = null; //???????¬????null?????????
			return temp; //???????¬??????£?????????temp?????????
		}else return this.next.pop(); //?¬?????¬????null??§????????£??????????¬????pop??????
	}
}

/**/

public class Main{

	static final int LEFT = 0;
	static final int RIGHT = 1;
	static final int UP = 2;
	static final int DOWN = 3;
	static final int factor[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320}; //1???????§????????????????????´????n?????????

	/**/
	//???????????\??????????????¢??°
	static public int hashkey(int[] cell){
		int val[] = new int[9];
		System.arraycopy(cell, 0, val, 0, 9);
		for(int i = 0; i < 9; i++){
			for(int j = i+1; j < 9; j++){
				if(val[j] > val[i]) val[j]--;
			}
		}
		//val??????0??????????????????????????????????????????????????????????????\?????¢????????°
		int hash = 0;
		for(int i = 0; i < 9; i++){
			hash += val[i]  * factor[8-i]; //factor????????§????????°?????????????????????????????????????????????
		}
		return hash;
	}

	/**/
	static public field dehash(int key){
		int cell[] = new int[9];
		for(int i = 0; i < 9; i++){
			cell[i] = key/factor[8-i]; //factor????????§????????°??????????????£????????????cell???val??¨??????
			key %= factor[8-i];//factor?????????????????????key???
		}
		for(int i = 8; i >= 0; i--){
			for(int j = i+1; j < 9; j++){
				if(cell[i] <= cell[j]) cell[j] ++;
			}
		}
		//hash??????key??????????????¨???val???cell??????????????????????????§??????cell???????????????dehash??§???????????¨????¢????
		return new field(cell, key);
	}

	/**/

	//3*3????????£????????????????§??????§????????????
	//move[i][LEFT]:??????????????????(0,1)
	//move[i][RIGHT]:??????????????????(0,1)
	//move[i][UP]:??????????????????(0,1)
	//move[i][DOWN]:??????????????????(0,1)
	static boolean move[][] = new boolean[9][4];

	public static void main(String[] args){
		
		//?§????????????????????¨??????¨???

		//?§??????§?????????????????????????????????????¨??????????
		//????????????????????????????????????
		move[0][RIGHT]=move[1][RIGHT]=move[3][RIGHT]=move[4][RIGHT]=move[6][RIGHT]=move[7][RIGHT]=true;
		move[2][RIGHT]=move[5][RIGHT]=move[8][RIGHT]=false;

		//????????????????????????????????????
		move[1][LEFT]=move[2][LEFT]=move[4][LEFT]=move[5][LEFT]=move[7][LEFT]=move[8][LEFT]=true;
		move[0][LEFT]=move[3][LEFT]=move[6][LEFT]=false;

		/**/
		//????????????????????????????????????
		move[3][UP]=move[4][UP]=move[5][UP]=move[6][UP]=move[7][UP]=move[8][UP]=true;
		move[0][UP]=move[1][UP]=move[2][UP]=false;

		//????????????????????????????????????
		move[0][DOWN]=move[1][DOWN]=move[2][DOWN]=move[3][DOWN]=move[4][DOWN]=move[5][DOWN]=true;
		move[6][DOWN]=move[7][DOWN]=move[8][DOWN]=false;

		/**/
		//????????????????¨??????¨???
		//????????????
		field st;
		int cell[] = new int[9];

		Scanner scan = new Scanner(System.in).useDelimiter("[\\s]+");
		for(int i=0;i<3;i++)
			for(int j=0;j<3;j++)
				cell[3*i+j] = scan.nextInt();
		//for?????°???????????§cell??\???

		st = new field(cell, hashkey(cell)); //??¨????????¢?????¨?????????????????¨???????????\??????????????£????????????????????????
		/**/
		//???????????\????????????
		boolean visited[] = new boolean[362880];
		for(int i=0; i<362880; i++)
			visited[i] = false;

		//??¢?´¢??¨???

		//??????????????????????¨????
		ev_list list = new ev_list();
		list.insert(new ev_list(st)); //?????????????????£?????????????????\??????
		visited[hashkey(cell)] = true; //???????????\????????????????????????true?????????

		/**/
		field cur;
		int hash;
		int count=0;
		while( (cur=list.pop() )!= null){
			count++; //??¢?´¢?????°???1?¢???????

			for(int i=0;i<9;i++){
				if(cur.cell[i]==0){ //cur????????¬???????????£????????????cell[i]???0??????
					if(move[i][LEFT]){ //?????????????????????????????¨??????
						cur.cell[i]=cur.cell[i-1];
						cur.cell[i-1]=0;
						hash=hashkey(cur.cell); //hashkey?????????
						if(!visited[hash]){ //hashkey????¨??????????????????????
							visited[hash]=true;
							list.insert(new ev_list(new field(cur.cell, cur.route, hash) )); //list????????£?????????????????\??????
						}
						cur.cell[i-1]=cur.cell[i]; //????????????
						cur.cell[i]=0;
					}
					/**/
					if(move[i][RIGHT]){ //?????????????????????????????¨??????
						cur.cell[i]=cur.cell[i+1];
						cur.cell[i+1]=0;
						hash=hashkey(cur.cell); //hashkey?????????
						if(!visited[hash]){ //hashkey????¨??????????????????????
							visited[hash]=true;
							list.insert(new ev_list(new field(cur.cell, cur.route, hash) ));
						}
						cur.cell[i+1]=cur.cell[i];
						cur.cell[i]=0;
					}
					if(move[i][UP]){ //?????????????????????????????¨??????
						cur.cell[i]=cur.cell[i-3];
						cur.cell[i-3]=0;
						hash=hashkey(cur.cell);
						if(!visited[hash]){
							visited[hash]=true;
							list.insert(new ev_list(new field(cur.cell, cur.route, hash) ));
						}
						cur.cell[i-3]=cur.cell[i];
						cur.cell[i]=0;
					}
					if(move[i][DOWN]){ //?????????????????????????????¨??????
						cur.cell[i]=cur.cell[i+3];
						cur.cell[i+3]=0;
						hash=hashkey(cur.cell); //hashkey?????????
						if(!visited[hash]){
							visited[hash]=true;
							list.insert(new ev_list(new field(cur.cell, cur.route, hash) ));
						}
						cur.cell[i+3]=cur.cell[i];
						cur.cell[i]=0;
					}
				}
			}
			/**/
			if(cur.evaluation==0){
				System.out.println(cur.route.length-1);
				//System.out.println(count+"");
				//System.out.println("evaluation[ "+0+" ]="+dehash(cur.route[0]).evaluation+"\n"+dehash(cur.route[0]) );
				//evaluation??¨???????????????cur.route[0]?????????????????\??????
				//for(int i=1;i<cur.route.length;i++){
					//System.out.println("???");
					//System.out.println("evaluation[ " +i+" ]="+dehash(cur.route[i]).evaluation);
					//System.out.println("evaluation+floor[ "+i+" ]="+(dehash(cur.route[i]).evaluation+i) );
					//evalution??¨???????????????floor?§?????????¢
					//System.out.println( dehash(cur.route[i]).toString() );
				//}
				break;
			}
		}
	}
}