Problem:
迷子の双子

たかゆき君とかずゆき君は仲良しの双子ですが、行動が真逆です。 例えば、たかゆき君が西に行けば、かずゆき君は東へ行き、かずゆき君が北へ行けば、たかゆき君は南へ行きます。 現在 2 人はデパートに来ており、別々の場所にいます。真逆に移動してしまう 2 人ができるだけ早く出会うためにはどうしたらよいでしょうか?

デパートは横 W 個 × 縦 H 個のマスで構成されるグリッドで表され、2 人は単位時間に東西南北に 1 マス分移動することができます。ただし、グリッドの範囲外や障害物のあるマスに移動することはできません。

図のように、グリッドのマスの位置は座標 (x, y) で表されます。

グリッドの情報と 2 人の初期位置を入力とし、2 人が出会うまでの最短の時間を出力するプログラムを作成してください。出会うことができない場合や、出会うのに 100 以上の時間を要する場合は、NA と出力してください。グリッドの情報は、H 行 W 列の数字、2 人の位置情報は座標によって与えられます。

移動後にたかゆき君かかずゆき君のうち、どちらか一方が障害物やグリッドの範囲外に位置してしまうときには、移動ができないので、障害物やグリッドの範囲外に位置する方は元の場所に戻りますが、そうでない方は元の場所に戻ることなく動くことができます。

なお、2 人が出会うとは、移動後に 2 人が同じマスに止まることを言います。2 人がすれ違っても、出会ったことにはなりません。

Input

複数のデータセットの並びが入力として与えられます。入力の終わりはゼロふたつの行で示されます。
各データセットは以下の形式で与えられます。

W H
tx ty
kx ky
d11 d21 ... dW1
d12 d22 ... dW2
:
d1H d2H ... dWH

1 行目にデパートの大きさW, H (1 ≤ W, H ≤ 50) が与えられます。2 行目にたかゆき君の初期位置 tx, ty、3 行目にかずゆき君の初期位置 kx, ky が与えられます。

続く H 行にデパートの情報が与えられます。di,j はマス (i, j) の種類を表し、0 のとき移動可能なマス、1 のとき障害物があるマスを表します。

データセットの数は 100 を超えません。

Output

入力データセットごとに、最短の時間を１行に出力します。

Sample Input

6 6
2 4
6 2
0 0 0 0 1 0
0 1 0 0 0 0
0 1 0 0 0 0
0 0 0 1 0 0
0 0 0 0 0 1
0 0 0 0 0 0
3 3
1 1
3 3
0 0 0
0 1 0
0 0 0
0 0

Output for the Sample Input

3
NA

Solution in JAVA (judge verdict: Memory Limit Exceeded)

import java.util.*;
public class Main {
	Scanner in = new Scanner(System.in);
	public static void main(String[] args) {
		new Main();
	}

	public Main() {
		new AOJ0223().doIt();
	}

	class AOJ0223{
		int x,y;
		
		void solve(){
			Person p1 = new Person(in.nextInt()-1, in.nextInt()-1);
			Person p2 = new Person(in.nextInt()-1, in.nextInt()-1);
			int[][] map = new int[y][x];
			int[][][][] memo = new int[y][x][y][x];
			int INF = Integer.MAX_VALUE/2;
			for(int i=0;i<y;i++)for(int s=0;s<x;s++)for(int k=0;k<y;k++)for(int r=0;r<x;r++)memo[i][s][k][r]=INF;
			memo[p1.y][p1.x][p2.y][p2.x] = 0;
			for(int i=0;i<y;i++)for(int s=0;s<x;s++)map[i][s] = in.nextInt();
			LinkedList<Data> q = new LinkedList<Data>();
			q.add(new Data(p1,p2,0));
			int sx[] = {1,0,-1,0};
			int sy[] = {0,1,0,-1};
			int sx2[] = {-1,0,1,0};
			int sy2[] = {0,-1,0,1};
			boolean isNA = true;
			int result = 0;
			while(q.size()>0){
				Data data = q.remove();
				Person t = data.p1;
				Person k = data.p2;
				if(data.cost>=100)continue;
				if(memo[t.y][t.x][k.y][k.x]<data.cost)continue;
				memo[t.y][t.x][k.y][k.x] = data.cost;
				if(t.x==k.x&&t.y==k.y){
					isNA = false;
					result = data.cost;break;
				}
				for(int i=0;i<4;i++){
					int nx1 = t.x+sx[i];
					int ny1 = t.y+sy[i];
					int nx2 = k.x+sx2[i];
					int ny2 = k.y+sy2[i];
					if(nx1<0||nx1>=x||ny1<0||ny1>=y){
						nx1 = t.x;ny1 = t.y;
					}
					if(map[ny1][nx1]==1){
						nx1 = t.x;ny1 = t.y;
					}
					if(nx2<0||nx2>=x||ny2<0||ny2>=y){
						nx2 = k.x;ny2 = k.y;
					}
					if(map[ny2][nx2]==1){
						nx2 = k.x;ny2 = k.y;
					}
					if(memo[ny1][nx1][ny2][nx2]<=data.cost+1)continue;
					q.add(new Data(new Person(nx1, ny1),new Person(nx2, ny2),data.cost+1));
				}
			}
			System.out.println(isNA==true? "NA":result);
		}

		void doIt(){
			while(true){
				x = in.nextInt();y = in.nextInt();
				if(x+y==0)break;
				solve();
			}
		}
		
		class Person{
			int x, y;
			public Person(int x,int y) {
				this.x = x;
				this.y = y;
			}
		}
		
		class Data{
			int cost;
			Person p1,p2;
			public Data(Person p1,Person p2,int cost) {
				this.p1 = p1;
				this.p2 = p2;
				this.cost = cost;
			}
			public String toString(){
				return p1.x+" "+p1.y+" ::: "+p2.x+" "+p2.y+" +++ "+cost;
			}
		}
	}


}