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)

// Aizu Vol-1 0121: Seven Puzzle 
// 2017.8.4

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

char *gets(char *);
char buf[100], *p;

int getInt(void)
{
	while (isspace(*p)) p++;
	return *p++ - '0';
}

#define MAGIC 37

typedef struct { char x; int a; } T;
T s[50]; int top;

#define HASHSIZ 37003		// must > 20160
typedef struct { int s; char v; } NODE;
NODE nd[HASHSIZ+5], *hashend = nd + HASHSIZ;

int lookup(int s)
{
	NODE *np = nd + s % HASHSIZ;
	while (1) {
		if (np->s == s) return np->v;
		if (np->s == 0) break;
		if (++np == hashend) np = nd;
	}
	return 0;
}

void insert(int s, char v)
{
	NODE *np = nd + s % HASHSIZ;
	while (1) {
		if (np->s == 0) { np->s = s, np->v = v; break; }
		if (np->s == s) { np->v = v; break; }
		if (++np == hashend) np = nd;
	}
}

char to[8][4] = {
	{ 1, 4, 10 }, { 0, 2, 5, 10 }, { 1, 3, 6, 10 }, { 2, 7, 10 },
	{ 0, 5, 10 }, { 1, 4, 6, 10 }, { 2, 5, 7, 10 }, { 3, 6, 10 } };

int swap(int a, int x, int y)
{
	int i, aa[10];

	for (i = 7; i >= 0; i--) aa[i] = a % 10, a /= 10;
	a = aa[x], aa[x] = aa[y], aa[y] = a;
	for (a = 0, i = 0; i < 8; i++) a = 10 * a + aa[i];
	return a;
}

int main()
{
	int x, a, i, j, n;

	s[0].a = 1234567, s[0].x = 0, top = 1, insert(1234567, 1);
	while (top > 0) {
		x = s[--top].x, a = s[top].a, n = lookup(a) + 1;
		if (n > MAGIC) continue;
		for (i = 0; (j = to[x][i]) < 10; i++) {
			int k = swap(a, x, j);
			int m = lookup(k);
			if (!m || m > n) s[top].a = k, s[top++].x = j, insert(k, n);
		}
	}
	while (gets(p = buf) != NULL) {
		for (i = 0, a = 0; i < 8; i++) a = a * 10 + getInt();
		printf("%d\n", lookup(a) - 1);
	}
	return 0;
}