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.io.*;
public class Main {
	private static IO io = new IO();
	public static void main(String[] args) {
		
		Map<Integer, Integer> ans = new HashMap<>();
		Deque<int[][]> que = new ArrayDeque<>();
		int init[] = {0,1,2,3,4,5,6,7};
		//0??????????????¶??????1??????????????????2??´?????????????????????3?§?????????°
		que.offer(new int[][] {init,{0},{-1},{0}});
		int dx[] = {-4, 1, 4, -1};
		
		while (!que.isEmpty()) {
			int[][] p = que.pollFirst();
			if (ans.containsKey(conv(p[0]))) continue;
			else ans.put(conv(p[0]), p[3][0]);
			//System.out.println(conv(p[0]));
			for (int i=0; i<4; i++) {
				int go = p[1][0] + dx[i];
				if (go==p[2][0] || go<0 || 7<go || (p[1][0]==3 && go==4) || (p[1][0]==4 && go==3)) continue;
				int next[];
				next = p[0].clone();
				swap(next, p[1][0], go);
				que.offer(new int[][] {next, {go}, {p[1][0]}, {p[3][0]+1}});
			}
		}
				
		while (io.hasNext()) {
			int q = 0;
			for (int i=0; i<=7; i++) {
				q += (io.nextInt()+1) * Math.pow(10, 7-i);
			}
			System.out.println(ans.get(q));
		}
	}
	
	private static void swap(int ar[], int a, int b) {
		int tmp = ar[a];
		ar[a] = ar[b];
		ar[b] = tmp;
	}
	
	private static int conv(int ar[]) {
		int ans = 0;
		for (int i=0; i<=7; i++) {
			ans += (ar[7-i]+1)*Math.pow(10, i);
		}
		return ans;
	}

	static class IO extends PrintWriter {
		private final InputStream in;
		private final byte[] buffer = new byte[1024];
		private int ptr = 0;
		private int buflen = 0;

		IO() { this(System.in);}
		IO(InputStream source) { super(System.out); this.in = source;}
		private boolean hasNextByte() {
			if (ptr < buflen) {
				return true;
			}else{
				ptr = 0;
				try {
					buflen = in.read(buffer);
				} catch (IOException e) {
					e.printStackTrace();
				}
				if (buflen <= 0) {
					return false;
				}
			}
			return true;
		}
		private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1;}
		private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
		private void skipUnprintable() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++;}
		boolean hasNext() { skipUnprintable(); return hasNextByte();}
		long nextLong() {
			if (!hasNext()) {
				throw new NoSuchElementException();
			}
			long n = 0;
			boolean minus = false;
			int b = readByte();
			if (b == '-') {
				minus = true;
				b = readByte();
			}
			if (b < '0' || '9' < b) {
				throw new NumberFormatException();
			}
			while(true){
				if ('0' <= b && b <= '9') {
					n *= 10;
					n += b - '0';
				}else if(b == -1 || !isPrintableChar(b)){
					return minus ? -n : n;
				}else{
					throw new NumberFormatException();
				}
				b = readByte();
			}
		}
		int nextInt() {
			long nl = nextLong();
			if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE) {
				throw new NumberFormatException();
			}
			return (int) nl;
		}
		public void close() {
			super.close();
			try {
				in.close();
			} catch (IOException ignored) {}
		}
	}
}