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: Memory Limit Exceeded)

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Set;

public class Main {
	public static void main(String[] args) throws Exception{
		try(Scanner sc = new Scanner(System.in)){
			while(sc.hasNextInt()){
				Queue<State> queue = new LinkedList<>();
				Set<Integer> set = new HashSet<>();
				int[][] firstNums = new int[2][4];
				int firstZeroX = -1;
				int firstZeroY = -1;
				for(int y = 0; y < 2; y++){
					for(int x = 0; x < 4; x++){
						firstNums[y][x] = sc.nextInt();
						if(firstNums[y][x] == 0){
							firstZeroY = y;
							firstZeroX = x;
						}
					}
				}

				State firstState = new State(firstNums, firstZeroY, firstZeroX, 0);
				set.add(firstState.hashCode());
				queue.add(firstState);

				while(!queue.isEmpty()){
					State nowState = queue.poll();
					if(nowState.hashCode() == 1234567){
						System.out.println(nowState.getDepth());
						break;
					}
					for(State nextState : nowState.nextMove()){
						if(!set.contains(nextState.hashCode())){
							set.add(nextState.hashCode());
							queue.add(nextState);
						}
					}
				}
			}
		}
	}

}

class State {

	private static final int[] vy = new int[]{0, 1, 0, -1};
	private static final int[] vx = new int[]{1, 0, -1, 0};

	private int[][] nums;
	private int zeroX;
	private int zeroY;
	private int hash;
	private int depth;

	public State(int[][] nums, int zeroY, int zeroX, int depth){
		this.nums = nums;
		this.zeroY = zeroY;
		this.zeroX = zeroX;
		this.depth = depth;
		this.hash = -1;
	}

	public int getDepth(){
		return depth;
	}

	public LinkedList<State> nextMove(){
		LinkedList<State> list = new LinkedList<>();
		for(int i = 0; i < 4; i++){
			int nextZeroY = zeroY + vy[i];
			int nextZeroX = zeroX + vx[i];
			if(nextZeroY < 0 || nextZeroY >= 2) continue;
			if(nextZeroX < 0 || nextZeroX >= 4) continue;
			int[][] nextNums = new int[2][4];
			for(int y = 0; y < 2; y++){
				for(int x = 0; x < 4; x++){
					nextNums[y][x] = nums[y][x];
				}
			}
			nextNums[nextZeroY][nextZeroX] = 0;
			nextNums[zeroY][zeroX] = nums[nextZeroY][nextZeroX];
			list.add(new State(nextNums, nextZeroY, nextZeroX, depth + 1));
		}

		return list;
	}

	@Override
	public int hashCode(){
		if(hash != -1) return hash;
		hash = 0;
		for(int y = 0; y < 2; y++){
			for(int x = 0; x < 4; x++){
				hash *= 10;
				hash += nums[y][x];
			}
		}
		return hash;
	}

}