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.io.*;
import java.lang.*;
import java.util.Scanner;
import java.util.Arrays;
import java.util.ArrayList;

class State {
    public byte map[][] = new byte [2][4];
    public State nextState[] = new State[4];
	public State parentState;
	public boolean isEndState(){
		int i;
		for(i = 0; i < 8; i++){
			if(this.map[i / 4][i % 4] != i){
				return false;
			}
		}
		return true;
	}
	public void extendTree(){
		int i;
		if(this.hasSameMapInHistory(this.map)){
			this.removeFromParent();
			return;
		}
		if(this.hasChild()){
			for(i = 0; i < 4; i++){
				if(this.nextState[i] != null){
					this.nextState[i].extendTree();
				}
			}
			return;
		}
		int p0x = 0, p0y = 0;
		for(i = 0; i < 8; i++){
			if(this.map[i / 4][i % 4] == 0){
				p0x = i % 4;
				p0y = i / 4;
				break;
			}
		}
		if(i == 8){
			return;
		}
		if(p0y == 1){
			this.nextState[0] = new State();
			this.nextState[0].copyFrom(this.map);
			this.nextState[0].exchange(p0x, 0, p0x, 1);
			this.nextState[0].parentState = this;
		}
		if(p0x != 3){
			this.nextState[1] = new State();
			this.nextState[1].copyFrom(this.map);
			this.nextState[1].exchange(p0x, p0y, p0x + 1, p0y);
			this.nextState[1].parentState = this;
		}
		if(p0y == 0){
			this.nextState[2] = new State();
			this.nextState[2].copyFrom(this.map);
			this.nextState[2].exchange(p0x, 0, p0x, 1);
			this.nextState[2].parentState = this;
		}
		if(p0x != 0){
			this.nextState[3] = new State();
			this.nextState[3].copyFrom(this.map);
			this.nextState[3].exchange(p0x, p0y, p0x - 1, p0y);
			this.nextState[3].parentState = this;
		}
	}
	public boolean hasChild(){
		int i;
		for(i = 0; i < 4; i++){
			if(this.nextState[i] != null){
				return true;
			}
		}
		return false;
	}
	public void copyFrom(byte src[][]){
		int i;
		for(i = 0; i < 8; i++){
			this.map[i / 4][i % 4] = src[i / 4][i % 4];
		}
	}
	public void printMap(){	
		System.out.println(Arrays.toString(this.map[0]));
		System.out.println(Arrays.toString(this.map[1]));
		System.out.println();
	}
	public void exchange(int px, int py, int qx, int qy){
		byte tmp;
		tmp = this.map[py][px];
		this.map[py][px] = this.map[qy][qx];
		this.map[qy][qx] = tmp;
	}
	public boolean hasEndState(){
		int i;
		if(this.hasChild()){
			for(i = 0; i < 4; i++){
				if(this.nextState[i] != null && this.nextState[i].hasEndState()){
					return true;
				}
			}
			return false;	
		}
		return this.isEndState();
	}
	public boolean hasSameMapInHistory(byte map[][]){
		if(this.parentState == null){
			return false;
		}
		int i;
		for(i = 0; i < 8; i++){
			if(this.parentState.map[i / 4][i % 4] != map[i / 4][i % 4]){
				return this.parentState.hasSameMapInHistory(map);
			}
		}
		return true;
	}
	public void removeFromParent(){
		int i;
		this.parentState.nextState[Arrays.asList(this.parentState.nextState).indexOf(this)] = null;
		for(i = 0; i < 4; i++){
			if(this.parentState.nextState[i] != null){
				break;
			}
		}
		if(i == 4){
			this.parentState.removeFromParent();
		}
		this.parentState = null;
	}
}

public class Main {
	public static void main(String[] args){
		InputStreamReader isr = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(isr);
		String buf;
		try {
			for(;;){
				State rootState = new State();
				buf = br.readLine();
				if(buf == null){
					break;
				}
				Scanner scanner = new Scanner(buf);
				if(!scanner.hasNext()){
					break;
				}
				int i;
				byte initState[][] = new byte[2][4];
				for(i = 0; i < 8; i++){
					initState[i / 4][i % 4] = scanner.nextByte();
				}
				rootState.copyFrom(initState);
				for(i = 0; ; i++){
					if(rootState.hasEndState()){
						System.out.println(i);
						break;
					}
					rootState.extendTree();
				}

			}
		}
		catch(IOException e) {
			System.out.println("Read error.");
			return;
		}
	}
}