Problem 0223 : Stray Twins

問題概要

日本語なので本文参照(http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/description.jsp?id=0223&lang=jp

w*h枚の正方形からなる長方形のグリッドであらわされるデパートに双子がいる。
デパートにはいくつかの障害物が存在する。
双子は上下左右に動けるが、一方は他方のちょうど逆の方向にしか動けない。
このとき、双子が同じマスに至るまでの最短の移動回数を求めよ。

解法

兄弟の位置をペアにしたノードについて幅優先探索をすればよい。
状態数は50*50*50*50で600万程度であるため十分間に合う。

ソースコード

int dy[]={-1,0,1,0},dx[]={0,-1,0,1};
int w,h,tx,ty,kx,ky;
int f[50][50];
bool v[50][50][50][50];

int main()
{
	while(scanf("%d%d",&w,&h),w)
	{
		scanf("%d%d%d%d",&tx,&ty,&kx,&ky);
		tx--; ty--; kx--; ky--;
		rep(i,h)rep(j,w)scanf("%d",f[i]+j);
		rep(i,h)rep(j,w)rep(k,h)rep(l,w)v[i][j][k][l]=0;
		
		v[tx][ty][kx][ky]=1;
		queue<pair<pair<pi,pi>,int> >Q;
		Q.push(mp(mp(mp(tx,ty),mp(kx,ky)),0));
		while(!Q.empty())
		{
			tx=Q.front().first.first.first; ty=Q.front().first.first.second;
			kx=Q.front().first.second.first; ky=Q.front().first.second.second;
			int cc=Q.front().second; Q.pop();
			
			rep(d,4)
			{
				int ntx=tx+dx[d],nty=ty+dy[d];
				int nkx=kx-dx[d],nky=ky-dy[d];
				
				if(ntx<0||ntx>=w||nty<0||nty>=h||f[nty][ntx])ntx=tx,nty=ty;
				if(nkx<0||nkx>=w||nky<0||nky>=h||f[nky][nkx])nkx=kx,nky=ky;
				if(v[ntx][nty][nkx][nky]||cc>=99)continue;
				if(ntx==nkx&&nty==nky)
				{
					printf("%d\n",cc+1); goto END;
				}
				Q.push(mp(mp(mp(ntx,nty),mp(nkx,nky)),cc+1));
				v[ntx][nty][nkx][nky]=1;
			}
		}
		puts("NA"); END:;
	}
	return 0;
}