N * Mは、マップは男の子、女の子と2人の幽霊を持って、マップを与えられました。
キャラクターが道路を表し、文字は 『X』の壁を表し、文字 『M』は、少年の位置を示し、文字 『G』は、女の子の位置を表す「」、文字 『Z』は、ゴーストの位置を示しています。
少年は単位距離あたりの3を移動させることができ、毎秒女の子は男の子と女の子は、わずか4つの方向に移動することができ、単位距離を移動することができます。
各ゴーストは、単位距離2〜4週間ごとに占有面積を拡大し、マンハッタン距離は、2kの位置を超えていないすべてのゴーストゴーストを占有するの後のk秒での隔壁、すなわちを無視することができます。
注意:毎秒ゴーストは最初、拡大男の子と移動することができます女の子の完了後に拡大していきます。
占領地のゴーストを入力するように求めずに、男の子と女の子が参加することができ、我々は満たしていれば、満たすために最短時間を見つけます。
入力形式
最初の行がT、Tは、テストケースの全セットを表す整数を含んでいます。
各テストケースの最初の行は、二つの整数NおよびMが含まれているマップのサイズを表します。
マップ全体の状態を記述するために使用されるM個の文字の次のNライン。(注意:マップは、唯一の男の子、一人の女の子と2人の幽霊を持っている必要があります)
出力フォーマット
各テスト出力整数Sは、最短の収束時間を表します。
あなたは出力に参加できない場合は-1。
各結果行。
データ範囲
1 < N 、M < 800 1 <N、M <800
サンプル入力:
3
5 6
XXXXXX
XZ..ZX
XXXXXX
M.G... ...... 5 6 XXXXXX XZZ..X XXXXXX M..... ..G... 10 10 .......... ..X....... ..M.X...X. X......... .X..X.X.X. .........X ..XX....X. X....G...X ...ZX.X... ...Z..X..X
出力例:
1
1
-1
アルゴリズム:BFS
ソリューション:
書式#include <iostreamの> の#include <cstdioを> する#include <キュー> 使用して名前空間はstdを、const int型 MAXN = 1E3 + 7 。構造体ノード{ int型X、Y、ステップと }。char型の地図[MAXN] [MAXN]。 INT DIR [ 4 ] [ 2 ] = { 0、 - 1、0、1、 - 1、0、1、0 }。 INTのN、M。ブールチェック(int型のx、 INTのY){ 場合(x <= 0 || X> N || Y <= 0 || Y> M){ 戻り 偽。 } を返す 真。 } int型BFS(){ キュー <ノード> 女の子、男の子、ゴースト。 以下のために(int型 i = 1 ; iが<= N; iは++ ){ ための(int型 J = 1 ; J <= Mであり、j ++ ){ 場合(地図[I] [J] == ' M ' ){ boy.push( (ノード){I、J、0}); } そう IF(マップ[I] [J] == ' G ' ){ girl.push((ノード){I、J、0 }); } そう IF(マップ[I] [J] == ' Z ' ){ ghost.push((ノード){I、J、0 }); } } } のための(INT I = 1 ; Iは<= 100005 ; Iは++){ // 列挙子が時間を反復処理するために INT TMP = 。ghost.front()+ステップ2 ; //は、移動距離を制限します 一方、(!。ghost.empty()&& ghost.front()ステップ< TMP){ ノードは今 = ghost.front()。 ghost.pop(); 用(INT J = 0 ; J < 4 ; J ++ ){ int型 TX = now.x + DIR [j] [ 0 ]。 INT TY = now.y + DIR [J] [ 1 ]。 もし(チェック(TX、TY)&&マップ[TX] [TY] =!' #' ){ ghost.push((ノード){TX、TY、now.step + 1 })。 地図[TX] [TY] =' #' ; 地図は[now.x] [now.y] = ' #' ; } } } TMP = boy.front()ステップ+ 3 。 一方、(!。boy.empty()&& boy.front()ステップ< TMP){ ノードは今 = boy.front()。 boy.pop(); 用(INT J = 0 ; J < 4 ; J ++ ){ int型 TX = now.x + DIR [j] [ 0 ]。 int型TY = now.y + DIR [J] [ 1 ]。 もし(チェック(TX、TY)&&地図[TX] [TY]!= ' #' ){ 場合(地図[TX] [TY] == ' ' ){ boy.push((ノード){TX、TY 、now.step + 1 })。 地図[TX] [TY] = ' M ' ; 地図[now.x] [now.y] = ' X ' ; } そうであれば(マップ[TX] [TY] == ' G ' ){ 戻りIと、 } } } } TMP = girl.front()工程+。1 。 一方、(!。girl.empty()&& girl.front()ステップ< TMP){ ノードは今 = girl.front()。 girl.pop(); 用(INT J = 0 ; J < 4 ; J ++ ){ int型 TX = now.x + DIR [j] [ 0 ]。 INT TY = now.y + DIR [J] [ 1 ]。 もし(チェック(TX、TY)&&マップ[TX] [TY]!= ' #' ){ 場合(地図[TX] [TY] == ' ' ){ girl.push((ノード){TX、TY、 now.step + 1 })。 地図[TX] [TY] = ' G ' 。 地図[now.x] [now.y] = ' X ' ; } そうであれば(マップ[TX] [TY] == ' M ' ){ リターンI。 } } } } } リターン - 1 。 } int型のmain(){ int型のT。 scanf関数(" %のD "、&T)。 一方、(T-- ){ scanf関数(" %d個の%のD "、&N、&M)。 以下のために(int型 i = 1 ; iが<= N; iは++ ){ GETCHAR()。 用(INT J = 1 ; J <= Mであり、j ++ ){ scanf関数("%のC "、&地図[I] [J]); } } のprintf(" %d個の\ n " 、BFS())。 } 戻り 0 。 }