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

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

class Program
{
    static readonly int H = 2, W = 4;
    int GoalKey;

    void Solve()
    {
        string s;
        int[,] A = new int[H, W];
        for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) A[i, j] = i * W + j;
        GoalKey = GetKey(A);
        while (true)
        {
            s = Console.ReadLine();
            if (string.IsNullOrEmpty(s)) break;
            Console.WriteLine(Go(s));
        }
    }

    int Go(string s)
    {
        var A = new int[H, W];
        int si = 0, sj = 0;
        for (int i = 0; i < H; i++)
            for (int j = 0; j < W; j++)
            {
                A[i, j] = int.Parse(s.Split()[i * W + j]);
                if (A[i, j] == 0) { si = i; sj = j; }
            }
        var que = new Queue<int[,]>();
        var queZeroIndex = new Queue<int>();
        var dic = new Dictionary<int, int>();
        dic[GetKey(A)] = 0;
        que.Enqueue(A);
        queZeroIndex.Enqueue(si);
        queZeroIndex.Enqueue(sj);

        while (que.Count > 0)
        {
            var curr = que.Dequeue();
            int i = queZeroIndex.Dequeue();
            int j = queZeroIndex.Dequeue();
            int key = GetKey(curr);
            if (key == GoalKey) return dic[key];

            for (int d = 0; d < di.Length; d++)
            {
                int ni = i + di[d], nj = j + dj[d];
                if (IsInside(ni, nj))
                {
                    int[,] next = new int[H, W];
                    for (int y = 0; y < H; y++) for (int x = 0; x < W; x++) next[y, x] = curr[y, x];
                    next[i, j] = next[ni, nj];
                    next[ni, nj] = 0;
                    int nextKey = GetKey(next);
                    if (!dic.ContainsKey(nextKey))
                    {
                        dic[nextKey] = dic[key] + 1;
                        que.Enqueue(next);
                        queZeroIndex.Enqueue(ni);
                        queZeroIndex.Enqueue(nj);
                    }
                }
            }
        }
        return int.MaxValue;
    }

    static readonly int[] di = { 0, 0, -1, 1 };
    static readonly int[] dj = { -1, 1, 0, 0 };
    bool IsInside(int i, int j)
    {
        return i >= 0 && i < H && j >= 0 && j < W;
    }

    int GetKey(int[,] A)
    {
        int key = 0;
        for (int i = 0; i < H; i++)
            for (int j = 0; j < W; j++)
                key = key * 8 + A[i, j];
        return key;
    }

    static void Main() { new Program().Solve(); }
    //static Read read = new Read();
    class Read
    {
        private Queue<string> que = new Queue<string>();
        public string String() { return Dequeue(); }
        public int Int() { return int.Parse(Dequeue()); }
        public long Long() { return long.Parse(Dequeue()); }
        public double Double() { return double.Parse(Dequeue()); }
        public int[] IntArray() { return Array.ConvertAll(Console.ReadLine().Split(), int.Parse); }
        public string[] StringArray(int N) { return Enumerable.Range(0, N).Select(i => Console.ReadLine()).ToArray(); }
        private string Dequeue()
        {
            if (que.Count == 0) foreach (var s in Console.ReadLine().Split()) que.Enqueue(s);
            return que.Dequeue();
        }
    }
}