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

<?php
//上の段の一番右のカードを、下の段の一番左のカードと交換してしまうミスに気をつけてください。

$file_handle = fopen('php://stdin', "r");	//fopen()は同位フォルダにファイルがあればその名前のみでOK
//$file_handle = fopen('aoj0121_in.txt', "r");

$goal = array(0,1,2,3,4,5,6,7);		//goal state
$move = array(-4, 1, 4, -1);	//0が↑→↓←に動く場合

//wfs
function wfs() {
	//グローバル変数定義
	global $goal;
	global $dist;
	global $ary_start;
	global $move;
	global $flag;
	
	$str = toString($ary_start);
	$visited[$str] = 1;				//最初の状態を探索済みに追加
	$queue[0] = $ary_start;			//スタートを$queueに入れて開始
	$queue[0]['dist'] = 0;
	while (!empty($queue)) {
	   $cur = array_shift($queue);	//$queueの『頭』から１つ取り出す。
	   
	   //終了条件
	   $cnt = 0;
	   for ($i=0; $i<=7; $i++) {
		   if ($cur[$i]!==$goal[$i]){
		       break;
		   }
		   $cnt++;
	   }
	   if ($cnt === 8){
	       $flag = 1;
	       $dist = $cur['dist'];
	       break;
	   }
	   
	   //探索ロジック
	   //０がどこにあるか
	   for ($i=0; $i<=7; $i++) {
	       if ($cur[$i]===0){
	           $zero = $i;
	           break;
	       }
	   }
	   
	   for ($i=0; $i<=3; $i++) {
	       //スワップ
	       $new_zero = $zero + $move[$i];		//ゼロの位置を移動
	       $new = $cur;		//バグの原因修正１。for文なので$curのままスワップ操作するとNG
	       if ($new_zero>=0 && !empty($new[$new_zero])) {
	           if ($zero===3 && $new_zero===4){ continue; }    //バグの修正２。
	           if ($zero===4 && $new_zero===3){ continue; }    //バグの修正２。
	           $new[$zero] = $new[$new_zero];
	           $new[$new_zero] = 0;
	           //未探索か
	           $str = toString($new);
	           if (empty($visited[$str])) {
				    $visited[$str] = 1;
				    $new['dist'] = $cur['dist'] + 1;
		    		array_push($queue, $new);
	           }
	       }
	   }
	}
}


//toString
function toString($ary){
	$str = '';
	foreach ($ary as $key => $val){
		if (is_numeric($key)) {		//配列のキーが数値ならば（distがあるので）
			$str = $str.$val;
		}
	}
	return $str;
}

while (1){
	//変数の初期化
	$flag = 0;
	$dist = 0;

	//ファイル読み込み
	$ary_start = fscanf($file_handle, '%d %d %d %d %d %d %d %d');
	//終了条件
	if ($ary_start === false){
		break;
	}
	
	//探索
	wfs();

	//出力
	if ($flag === 1){
		echo $dist;
	} else {
		echo 'ERROR';
	}
	echo PHP_EOL;
}

fclose($file_handle);