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<stdlib.h>
#include<string.h>
int d[40320],f,l,i,j,k;
char Q[50000][9];

int h(char n[8])
{
	char c[8];
	int f[8]={5040,720,120,24,6,2,1,0},i,j,v= 0;
	memcpy(c,n,8);
	for(i=0;i<7;i++){
		v += f[i] * (c[i]-'0');
		for(j=i+1;j<8;j++){
		if(c[i]<c[j])c[j]--;
		}
	}
	return v;
}

void enq(char s[9])
{
	strcpy(Q[l++],s);
}

int main()
{
	int m[4]={1,4,-4,-1};
	char s[9]={48,49,50,51,52,53,54,55,0},c[18],w[9],t;
	memset(d,-1,sizeof(d));
	d[h("01234567")]=0;
	enq(s);
	while(l!=f)
	{
		strcpy(s,Q[f++]);
		strcpy(w,s);
		for(i=0;i<8;i++)
			if(s[i]=='0')
				break;
		if(i==3)
			j=1,k=4;
		else if(i==4)
			j=0,k=3;
		else
			j=0,k=4;
		for(;j<k;j++)
			if(i+m[j]>=0&&i+m[j]<8)
			{
				t=s[i+m[j]];
				s[i+m[j]]=s[i];
				s[i]=t;
				int x=h(s);
				int y=h(w);
				if(d[x]==-1||d[x]>d[y]+1)
				{
					d[x]=d[y]+1;
					enq(s);
				}
				strcpy(s,w);
			}
	}
	while((c[0]=getchar())!=-1)
	{
		for(i=1;i<16;i++)
			c[i]=getchar();
		for(i=0,j=0;i<8;i++,j+=2)
			s[i]=c[j];
		printf("%d\n",d[h(s)]);
	}
	return 0;
}