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 C (judge verdict: Accepted)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int m,n;
int i,j,set,mark[8][8][8][8][8][8][8],q[1000000][10];

void swap (int* x,int* y){
	int z;
	z=*x;
	*x=*y;
	*y=z;
}

int check(int a[]){
	int k;
	for(k=0;k<8;k++){if(a[k]!=k)return 0;}
	return 1;
}

int look(int a[],int dir){
	j++;
	int k;
	for(k=0;k<10;k++)q[j][k]=a[k];
	if(dir==0){swap(&q[j][q[j][8]],&q[j][q[j][8]-1]);q[j][8]--;}
	if(dir==1){swap(&q[j][q[j][8]],&q[j][q[j][8]+1]);q[j][8]++;}
	if(dir==2){swap(&q[j][q[j][8]],&q[j][q[j][8]-4]);q[j][8]-=4;}
	if(dir==3){swap(&q[j][q[j][8]],&q[j][q[j][8]+4]);q[j][8]+=4;}
	q[j][9]++;
	if(mark[q[j][0]][q[j][1]][q[j][2]][q[j][3]][q[j][4]][q[j][5]][q[j][6]]==set){j--;return 0;}
	else mark[q[j][0]][q[j][1]][q[j][2]][q[j][3]][q[j][4]][q[j][5]][q[j][6]]=set;
	if(check(q[j]))return q[j][9]; else return 0;
}

int inspect(int a[]){
	if(a[8]%4>0 && look(a,0))return q[j][9];
	if(a[8]%4<3 && look(a,1))return q[j][9];
	if(a[8]>3 && look(a,2))return q[j][9];
	if(a[8]<4 && look(a,3))return q[j][9];
	return 0;
}


int main(){
	while(1){
		set++;
		for(i=0;i<8;i++){
			if(scanf("%d",&q[0][i])==EOF)goto exit;
			if(q[0][i]==0)q[0][8]=i;
		}
		q[0][9]=0;
		if(check(q[0]))printf("0\n");
		else{
			i=0;j=0;
			mark[q[0][0]][q[0][1]][q[0][2]][q[0][3]][q[0][4]][q[0][5]][q[0][6]]=set;
			while(!inspect(q[i])){
				i++;
			}
			printf("%d\n",q[j][9]);
		}
	}
	exit:;
	return 0;
}