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 GoalMask;

    void Solve()
    {
        GoalMask = 0;
        for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) Set(i, j, i * W + j, ref GoalMask);
        //var input = new List<string>();
        string s;
        int count = 0;
        while (!string.IsNullOrEmpty(s = Console.ReadLine()))
        {
            if (count++ == 1000) throw new Exception();
            Console.WriteLine(Go(s));
        }
        //var ans = input.Select(init => Go(init));
        //Console.WriteLine(string.Join("\n", ans));
    }

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

        while (que.Count > 0)
        {
            mask = que.Dequeue();
            int i = que.Dequeue();
            int j = que.Dequeue();
            if (mask == GoalMask) return dic[mask];

            for (int d = 0; d < di.Length; d++)
            {
                int ni = i + di[d], nj = j + dj[d];
                if (IsInside(ni, nj))
                {
                    int next = mask;
                    Set(i, j, Get(ni, nj, next), ref next);
                    Set(ni, nj, 0, ref next);
                    if (!dic.ContainsKey(next))
                    {
                        dic[next] = dic[mask] + 1;
                        que.Enqueue(next);
                        que.Enqueue(ni);
                        que.Enqueue(nj);
                    }
                }
            }
        }
        return int.MaxValue;
    }

    int Get(int i, int j, int mask)
    {
        return (mask >> (3 * (i * W + j))) & 7;
    }
    void Set(int i, int j, int num, ref int mask)
    {
        mask &= ~(7 << (3 * (i * W + j)));
        mask |= num << (3 * (i * W + j));
    }

    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;
    }

    static void Main()
    {
        //var sw = Stopwatch.StartNew();
        //var p = new Program();
        //int[] a = Enumerable.Range(0, 8).ToArray();
        //int count = 0;
        //do
        //{
        //    if (count++ == 1000) break;
        //    string s = "";
        //    for (int i = 0; i < 8; i++)
        //    {
        //        s += (i > 0 ? " " : "") + a[i];
        //    }
        //    p.Go(s);

        //} while (NextPermutation(a));

        //var ms = sw.ElapsedMilliseconds;

        //Console.WriteLine(ms + "ms");
        //Console.WriteLine("done");
        //Console.ReadLine();
        new Program().Solve(); 
    }


    static bool NextPermutation<T>(T[] a)
    {
        Comparer<T> comp = Comparer<T>.Default;
        for (int i = a.Length - 2; i >= 0; i--)
        {
            if (comp.Compare(a[i], a[i + 1]) < 0)
            {
                int j = a.Length - 1;
                while (comp.Compare(a[i], a[j]) >= 0) { j--; }
                T tmp = a[i]; a[i] = a[j]; a[j] = tmp;
                Array.Reverse(a, i + 1, a.Length - 1 - i);
                return true;
            }
        }
        return false;
    }
    //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();
        }
    }
}