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

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

typedef struct {
    int num[2][4];
    int time;
    int hash;
    int x, y;
} PUZZLE;

PUZZLE queue[50000];
int head, tail;

void enq(PUZZLE t)
{
    queue[(tail++) % 50000] = t;
}

void deq(PUZZLE *t)
{
    *t = queue[(head++) % 50000];
}

int seven(int num[][4])
{
    int i, j;
    char flag;
    
    flag = 1;
    
    for (i = 0; i < 2; i++){
        for (j = 0; j < 4; j++){
            if (num[i][j] != j + i * 4){
                flag = 0;
                break;
            }
        }
    }
    
    return (flag);
}

int generateHash(int num[][4])
{
    int i, j, ret;
    int pow;
    
    pow = 1;
    ret = 0;
    for (i = 0; i < 2; i++){
        for (j = 0; j < 4; j++){
            ret += pow * num[i][j];
            pow *= 8;
        }
    }
    return (ret);
}

int main(void)
{
    PUZZLE first, temp;
    char str[30];
    static char v[200000000];
    int i, j;
    int dx[4] = {1, 0, -1, 0};
    int dy[4] = {0, 1, 0, -1};
    
    while (scanf("%[^\n]", str) != EOF){
        getchar();
        for (i = 0; i < 2; i++){
            for (j = 0; j < 4; j++){
                first.num[i][j] = str[j * 2 + i * 8] - '0';
                if (first.num[i][j] == 0){
                    first.x = j;
                    first.y = i;
                }
            }
        }
        
        memset(v, 0, sizeof(v));
        
        first.time = 0;
        first.hash = generateHash(first.num);
        v[first.hash] = 1;
        head = tail = 0;
        enq(first);
        
        while (1){
            deq(&temp);
            if (seven(temp.num) == 1){
                break;
            }
            
            for (i = 0; i < 4; i++){
                first = temp;
                first.time = temp.time + 1;
                first.x += dx[i];
                first.y += dy[i];
                if (0 <= first.x && first.x < 4 && 0 <= first.y && first.y < 2){
                    first.num[temp.y][temp.x] ^= first.num[first.y][first.x];
                    first.num[first.y][first.x] ^= first.num[temp.y][temp.x];
                    first.num[temp.y][temp.x] ^= first.num[first.y][first.x];
                    first.hash = generateHash(first.num);
                    if (!v[first.hash]){
                        v[first.hash] = 1;
                        enq(first);
                    }
                }
            }
        }
        
        printf("%d\n", temp.time);
    }
    
    return (0);
}