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++11 (judge verdict: Time Limit Exceeded)

#include <cstdio>
#include <vector>
#include <iostream>

const int N = 8;
int CACHE[N] = {0,1,2,3,4,5,6,7};
int CANDIDATE[N] = {0,1,2,3,4,5,6,7};
const int FACTORIAL[N] = {1,1,2,6, 24,120,720,5040};

const int MAX_STATE = 5040;
int DIST[MAX_STATE];

int cache2num()
{
	int result=0;
	bool is_available[N] = {true,true,true,true,true,true,true,true,};
	for(int i=0;i<N;i++)
	{
		int cp=0;
		for(int j=0;j<CACHE[i];j++)
			if(is_available[j])		cp+=1;
		result += cp*FACTORIAL[N-1-i];
		is_available[CACHE[i]]=false;
	}
	return result;
}
int cand2num()
{
	int result=0;
	bool is_available[N] = {true,true,true,true,true,true,true,true,};
	for(int i=0;i<N;i++)
	{
		int cp=0;
		for(int j=0;j<CANDIDATE[i];j++)
			if(is_available[j])		cp+=1;
		result += cp*FACTORIAL[N-1-i];
		is_available[CANDIDATE[i]]=false;
	}
	return result;
}
void cache2cand()
{
	for(int i=0;i<N;i++)
		CANDIDATE[i]=CACHE[i];
}
void num2cache(int num)
{
	bool is_available[N] = {true,true,true,true,true,true,true,true,};
	for(int i=0;i<N;i++)
	{
		int order = num/FACTORIAL[N-1-i];
		num = num % FACTORIAL[N-1-i];
		int index=0;
		while(!is_available[index])
			index++;
		for(int cp=0;cp<order;index++)
			if(is_available[index+1])
				cp++;
		CACHE[i] = index;
		is_available[index]=false;
	}
}
void print_cache()
{
	std::cout << "cache:";
	for(int i=0;i<N;i++)
		std::cout << CACHE[i] << ",";
	std::cout << std::endl;
}
void print_candidate()
{
	std::cout << "cand :";
	for(int i=0;i<N;i++)
		std::cout << CANDIDATE[i] << ",";
	std::cout << std::endl;
}
void swap(int i,int j)
{
	int tmp = CACHE[i];
	CACHE[i] = CACHE[j];
	CACHE[j] = tmp;
}
////////////////////////////////////
// left rotate
void rorate1L()
{
	int tmp 	 = CANDIDATE[1];
	CANDIDATE[1] = CANDIDATE[5];
	CANDIDATE[5] = CANDIDATE[4];
	CANDIDATE[4] = tmp;
}
void rorate2L()
{
	int tmp 	 = CANDIDATE[1];
	CANDIDATE[1] = CANDIDATE[2];
	CANDIDATE[2] = CANDIDATE[6];
	CANDIDATE[6] = CANDIDATE[5];
	CANDIDATE[5] = CANDIDATE[4];
	CANDIDATE[4] = tmp;
}
void rorate3L()
{
	int tmp 	 = CANDIDATE[1];
	CANDIDATE[1] = CANDIDATE[2];
	CANDIDATE[2] = CANDIDATE[3];
	CANDIDATE[3] = CANDIDATE[7];
	CANDIDATE[7] = CANDIDATE[6];
	CANDIDATE[6] = CANDIDATE[5];
	CANDIDATE[5] = CANDIDATE[4];
	CANDIDATE[4] = tmp;
}
////////////////////////////////////
// right rotate
void rorate1R()
{
	int tmp 	 = CANDIDATE[4];
	CANDIDATE[4] = CANDIDATE[5];
	CANDIDATE[5] = CANDIDATE[1];
	CANDIDATE[1] = tmp;
}
void rorate2R()
{
	int tmp 	 = CANDIDATE[4];
	CANDIDATE[4] = CANDIDATE[5];
	CANDIDATE[5] = CANDIDATE[6];
	CANDIDATE[6] = CANDIDATE[2];
	CANDIDATE[2] = CANDIDATE[1];
	CANDIDATE[1] = tmp;
}
void rorate3R()
{
	int tmp 	 = CANDIDATE[4];
	CANDIDATE[4] = CANDIDATE[5];
	CANDIDATE[5] = CANDIDATE[6];
	CANDIDATE[6] = CANDIDATE[7];
	CANDIDATE[7] = CANDIDATE[3];
	CANDIDATE[3] = CANDIDATE[2];
	CANDIDATE[2] = CANDIDATE[1];
	CANDIDATE[1] = tmp;
}

////////////////////////////////////
// solve
int solve()
{
	int step=0;

//	for(int i=0;i<40;i++)
//	std::cout << '=';
//	std::cout << std::endl;

	// let CACHE[0]==0 and calculate step
	int zero_position=0;
	for(;zero_position<N;zero_position++)
		if(CACHE[zero_position]==0)	break;
	int col = zero_position%(N/2);
	int row = zero_position/(N/2);
	if(row==1)
	{
		step++;
		swap(col,col+4);
	}
	while(col!=0)
	{
		step++;
		swap(col-1,col);
		col--;
	}

	// reset distance
	for(int i=0;i<MAX_STATE;i++)
		DIST[i] = MAX_STATE;
	// init frontier
	std::vector<int> frontier(1,cache2num());
	DIST[frontier[0]] = step;

	int cand_num;
	while(frontier.size()!=0)
	{
		std::vector<int> next_frontier;
		for(auto n : frontier)
		{
			num2cache(n);

			int zero_position=0;
			for(;zero_position<N;zero_position++)
				if(CACHE[zero_position]==0)	break;

			col = zero_position%(N/2);
			row = zero_position/(N/2);

			// 3 right rotation
			if(CACHE[3]!=3 || CACHE[7]!=7)
			{
				cache2cand();
				rorate3R();
				cand_num = cand2num();
				if(DIST[n]+8<DIST[cand_num])
				{
					DIST[cand_num] = DIST[n]+8;
					if(cand_num!=0)
						next_frontier.push_back(cand_num);
				}
			}
			// 3 left rotation
			if(CACHE[3]!=3 || CACHE[7]!=7)
			{
				cache2cand();
				rorate3L();
				cand_num = cand2num();
				if(DIST[n]+8<DIST[cand_num])
				{
					DIST[cand_num] = DIST[n]+8;
					if(cand_num!=0)
						next_frontier.push_back(cand_num);
				}
			}
			// 2 right rotation
			if(CACHE[2]!=2 || CACHE[6]!=6)
			{
				cache2cand();
				rorate2R();
				cand_num = cand2num();
				if(DIST[n]+6<DIST[cand_num])
				{
					DIST[cand_num] = DIST[n]+6;
					if(cand_num!=0)
						next_frontier.push_back(cand_num);
				}
				cache2cand();
			}
			// 2 left rotation
			if(CACHE[2]!=2 || CACHE[6]!=6)
			{
				rorate2L();
				cand_num = cand2num();
				if(DIST[n]+6<DIST[cand_num])
				{
					DIST[cand_num] = DIST[n]+6;
					if(cand_num!=0)
						next_frontier.push_back(cand_num);
				}

			}

			// 1 right rotation
			if(CACHE[1]!=1 || CACHE[5]!=5)
			{
				cache2cand();
				rorate1R();
				cand_num = cand2num();
				if(DIST[n]+4<DIST[cand_num])
				{
					DIST[cand_num] = DIST[n]+4;
					if(cand_num!=0)
						next_frontier.push_back(cand_num);
				}
			}
			// 1 left rotation
			if(CACHE[1]!=1 || CACHE[5]!=5)
			{
				cache2cand();
				rorate1L();
				cand_num = cand2num();
				if(DIST[n]+4<DIST[cand_num])
				{
					DIST[cand_num] = DIST[n]+4;
					if(cand_num!=0)
						next_frontier.push_back(cand_num);
				}
			}
		}
		frontier = next_frontier;
	}
	return DIST[0];
}
int main()
{
	char cline[16];
	std::cin.getline(cline, sizeof(cline));
	while(0<=cline[0]-'0' && cline[0]-'0'<8)
	{
		int cp = 0;
		for(int i=0;i<16;i++)
			if(isdigit(cline[i]))
				CACHE[cp++]=cline[i]-'0';
		std::cout << solve() << std::endl;
		std::cin.getline(cline, sizeof(cline));
	}
	return 0;
}



/*

0 1 2 3 4 5 6 7
1 0 2 3 4 5 6 7
7 6 5 4 3 2 1 0


0
1
28
*/