Problem:
7 パズル

7 パズルは 8 つの正方形のカードとこれらのカードがぴたりと収まる枠で構成されています。それぞれのカードには、互いに区別できるように 0, 1, 2, ..., 7 と番号がつけられています。枠には、縦に 2 個、横に 4 個のカードを並べることができます。

7 パズルを始めるときには、まず枠にすべてのカードを入れます。枠のなかで 0 のカードだけは、上下左右に隣接するカードと位置を交換することができます。たとえば、枠の状態が図(a) のときに、0 のカードの右に隣接した、7 のカードと位置を交換すれば、図(b) の状態になります。あるいは、図(a) の状態から 0 のカードの下に隣接した 2 のカードと位置を交換すれば図(c) の状態になります。図(a) の状態で 0 のカードと上下左右に隣接するカードは 7 と 2 のカードだけなので、これ以外の位置の入れ替えは許されません。

ゲームの目的は、カードをきれいに整列して図(d) の状態にすることです。最初の状態を入力とし、カードをきれいに整列するまでに、必要な最小手数を出力するプログラムを作成してください。ただし、入力されたカードの状態からは図(d) の状態に移ることは可能であるとします。

入力データは、1 行に 8 つの数字が空白区切りで与えられます。これらは、最初の状態のカードの並びを表します。例えば、図(a) の数字表現は0 7 3 4 2 5 1 6 に、図(c) は 2 7 3 4 0 5 1 6 となります。

図(a) 0 7 3 4 2 5 1 6 の場合

図(b) 7 0 3 4 2 5 1 6 の場合

図(c) 2 7 3 4 0 5 1 6 の場合

図(d) 0 1 2 3 4 5 6 7 (最終状態)

Input

上記形式で複数のパズルが与えられます。入力の最後まで処理してください。
与えられるパズルの数は 1,000 以下です。

Output

各パズルについて、最終状態へ移行する最小手数を１行に出力してください。

Sample Input

0 1 2 3 4 5 6 7
1 0 2 3 4 5 6 7
7 6 5 4 3 2 1 0

Output for the Sample Input

0
1
28

Solution in JAVA (judge verdict: Accepted)

import java.util.*;
import java.lang.*;
import java.math.*;
import java.io.*;

import static java.lang.Math.*;
import static java.util.Arrays.*;

public class Main{

	Scanner sc=new Scanner(System.in);

	int INF=1<<28;
	double EPS=1e-9;

	HashMap<Integer, Integer> map;
	int[] a;
	int w=4, h=2;

	void run(){
		a=new int[w*h];
		init();
		for(; sc.hasNext();){
			for(int i=0; i<w*h; i++){
				a[i]=sc.nextInt();
			}
			println(""+map.get(id(a)));
		}
	}

	void init(){

		LinkedList<S> que=new LinkedList<S>();
		map=new HashMap<Integer, Integer>();

		que.offer(new S(0, 0, new int[]{0, 1, 2, 3, 4, 5, 6, 7}));
		map.put(id(que.peek().a), 0);
		int[] dx={0, 0, -1, 1};
		int[] dy={-1, 1, 0, 0};

		for(; !que.isEmpty();){
			S s=que.poll();
			int p=s.y*w+s.x;
			for(int i=0; i<4; i++){
				int x2=s.x+dx[i];
				int y2=s.y+dy[i];
				int p2=y2*w+x2;
				if(x2>=0&&x2<w&&y2>=0&&y2<h){
					int[] a2=s.a.clone();
					int t=a2[p];
					a2[p]=a2[p2];
					a2[p2]=t;
					S s2=new S(x2, y2, a2);
					if(!map.containsKey(id(s2.a))){
						que.offer(s2);
						map.put(id(s2.a), map.get(id(s.a))+1);
					}
				}
			}
		}
		/*
		 * debug("here");
		 * debug(map.get(1234567));
		 * debug(map.get(10234567));
		 * debug(map.get(76543210));
		 */
	}

	int id(int[] a){
		int res=0;
		for(int e : a){
			res=res*10+e;
		}
		return res;
	}

	/*
	 * void solve(){
	 * int x=-1, y=-1;
	 * for(int i=0; i<w*h; i++){
	 * if(a[i]==0){
	 * x=i%w;
	 * y=i/w;
	 * }
	 * }
	 * 
	 * LinkedList<S> que=new LinkedList<S>();
	 * TreeSet<Integer> set=new TreeSet<Integer>();
	 * 
	 * que.offer(new S(x, y, a, 0));
	 * set.add(que.peek().id);
	 * int[] dx={0, 0, -1, 1};
	 * int[] dy={-1, 1, 0, 0};
	 * 
	 * for(; !que.isEmpty();){
	 * S s=que.poll();
	 * 
	 * if(s.id==1234567){
	 * println(""+s.cnt);
	 * return;
	 * }
	 * 
	 * int p=s.y*w+s.x;
	 * for(int i=0; i<4; i++){
	 * int x2=s.x+dx[i];
	 * int y2=s.y+dy[i];
	 * int p2=y2*w+x2;
	 * if(x2>=0&&x2<w&&y2>=0&&y2<h){
	 * int[] a2=s.a.clone();
	 * int t=a2[p];
	 * a2[p]=a2[p2];
	 * a2[p2]=t;
	 * S s2=new S(x2, y2, a2, s.cnt+1);
	 * if(!set.contains(s2.id)){
	 * que.offer(s2);
	 * set.add(s2.id);
	 * }
	 * }
	 * }
	 * }
	 * }
	 */

	class S{
		int x, y;
		int[] a;

		S(int x, int y, int[] a){
			this.x=x;
			this.y=y;
			this.a=a;
		}
	}

	void debug(Object... os){
		System.err.println(Arrays.deepToString(os));
	}

	void print(String s){
		System.out.print(s);
	}

	void println(String s){
		System.out.println(s);
	}

	public static void main(String[] args){
		// System.setOut(new PrintStream(new BufferedOutputStream(System.out)));
		new Main().run();
	}
}