Problem:
Score : 400 points

Problem Statement

A maze is composed of a grid of H \times W squares - H vertical, W horizontal.

The square at the i-th row from the top and the j-th column from the left - (i,j) - is a wall if S_{ij} is # and a road if S_{ij} is ..

There is a magician in (C_h,C_w). He can do the following two kinds of moves:

Move A: Walk to a road square that is vertically or horizontally adjacent to the square he is currently in.

Move B: Use magic to warp himself to a road square in the 5\times 5 area centered at the square he is currently in.

In either case, he cannot go out of the maze.

At least how many times does he need to use the magic to reach (D_h, D_w)?

Constraints

1 \leq H,W \leq 10^3

1 \leq C_h,D_h \leq H

1 \leq C_w,D_w \leq W

S_{ij} is # or ..

S_{C_h C_w} and S_{D_h D_w} are ..

(C_h,C_w) \neq (D_h,D_w)

Input

Input is given from Standard Input in the following format:

H W
C_h C_w
D_h D_w
S_{11}\ldots S_{1W}
\vdots
S_{H1}\ldots S_{HW}

Output

Print the minimum number of times the magician needs to use the magic. If he cannot reach (D_h,D_w), print -1 instead.

Sample Input 1

4 4
1 1
4 4
..#.
..#.
.#..
.#..

Sample Output 1

1

For example, by walking to (2,2) and then using the magic to travel to (4,4), just one use of magic is enough.

Note that he cannot walk diagonally.

Sample Input 2

4 4
1 4
4 1
.##.
####
####
.##.

Sample Output 2

-1

He cannot move from there.

Sample Input 3

4 4
2 2
3 3
....
....
....
....

Sample Output 3

0

No use of magic is needed.

Sample Input 4

4 5
1 2
2 5
#.###
####.
#..##
#..##

Sample Output 4

2

Solution in Java (OpenJDK 1.8.0) (judge verdict: Wrong Answer)

import java.io.*;
import java.math.*;
import java.util.*;
public class Main {
	/**/
	public static void main(String[] args) {  
		FastScanner I = new FastScanner(); //Input
		OutPut O = new OutPut(); //Output
		int R = I.nextInt();
		int C = I.nextInt();
		int r1 = I.nextInt()-1;
		int c1 = I.nextInt()-1;
		int r2 = I.nextInt()-1;
		int c2 = I.nextInt()-1;
		char[][] grid = new char[R][C];
		long ans = Integer.MAX_VALUE;
		for (int i = 0; i < R; i++) grid[i] = I.next().toCharArray();
		for (int i = 1000; i <= 4321; i++) {
			String chk = Integer.toString(i);
			boolean[] vis = new boolean[5];
			int cnt = 0;
			for (int j = 0; j < 4; j++) {
				int dig = chk.charAt(j)-'0';
				if (dig<=4&&!vis[dig]) {
					cnt++;
					vis[dig]=true;
				}
			}
			if (cnt==4) { //if actually a permutation
				long[][] dp = new long[R][C]; //dp[i][j] holds minimum magic to get to square (i,j)
				for (int ix = 0; ix < R; ix++) {
					for (int jx = 0; jx < C; jx++) {
						dp[ix][jx] = Integer.MAX_VALUE;
					}
				}
				dp[r1][c1]=0; //Already here
				for (int j = 0; j < 4; j++) {
					if (chk.charAt(j)=='1') {
						for (int r = r1; r < R; r++) {
							for (int c = c1; c < C; c++) {
								if (grid[r][c]=='.') {
									if (r>0) dp[r][c]=min(dp[r][c],dp[r-1][c]);
									if (c>0) dp[r][c]=min(dp[r][c],dp[r][c-1]);
									if (r+1<R) dp[r][c]=min(dp[r][c],dp[r+1][c]);
									if (c+1<C) dp[r][c]=min(dp[r][c],dp[r][c+1]);
									for (int backr = max(r-2,0); backr<=min(r+2,R-1); backr++) {
										for (int backc = max(c-2,0); backc<=min(c+2,C-1); backc++) {
											dp[r][c]=min(dp[r][c],dp[backr][backc]+1); //Magic check
											//Obstacles will be huge numbers, 
											//therefore no affect on final answer
										}
									}
								}			
							}
						}
					}else if (chk.charAt(j)=='2') {
						for (int r = r1; r >= 0; r--) {
							for (int c = c1; c < C; c++) {
								if (grid[r][c]=='.') {
									if (r>0) dp[r][c]=min(dp[r][c],dp[r-1][c]);
									if (c>0) dp[r][c]=min(dp[r][c],dp[r][c-1]);
									if (r+1<R) dp[r][c]=min(dp[r][c],dp[r+1][c]);
									if (c+1<C) dp[r][c]=min(dp[r][c],dp[r][c+1]);
									for (int backr = max(r-2,0); backr<=min(r+2,R-1); backr++) {
										for (int backc = max(c-2,0); backc<=min(c+2,C-1); backc++) {
											dp[r][c]=min(dp[r][c],dp[backr][backc]+1); //Magic check
											//Obstacles will be huge numbers, 
											//therefore no affect on final answer
										}
									}
								}			
							}
						}
					}else if (chk.charAt(j)=='3') {
						for (int r = r1; r >= 0; r--) {
							for (int c = c1; c >= 0; c--) {
								if (grid[r][c]=='.') {
									if (r>0) dp[r][c]=min(dp[r][c],dp[r-1][c]);
									if (c>0) dp[r][c]=min(dp[r][c],dp[r][c-1]);
									if (r+1<R) dp[r][c]=min(dp[r][c],dp[r+1][c]);
									if (c+1<C) dp[r][c]=min(dp[r][c],dp[r][c+1]);
									for (int backr = max(r-2,0); backr<=min(r+2,R-1); backr++) {
										for (int backc = max(c-2,0); backc<=min(c+2,C-1); backc++) {
											dp[r][c]=min(dp[r][c],dp[backr][backc]+1); //Magic check
											//Obstacles will be huge numbers, 
											//therefore no affect on final answer
										}
									}
								}			
							}
						}
					}else {
						for (int r = r1; r < R; r++) {
							for (int c = c1; c >= 0; c--) {
								if (grid[r][c]=='.') {
									if (r>0) dp[r][c]=min(dp[r][c],dp[r-1][c]);
									if (c>0) dp[r][c]=min(dp[r][c],dp[r][c-1]);
									if (r+1<R) dp[r][c]=min(dp[r][c],dp[r+1][c]);
									if (c+1<C) dp[r][c]=min(dp[r][c],dp[r][c+1]);
									for (int backr = max(r-2,0); backr<=min(r+2,R-1); backr++) {
										for (int backc = max(c-2,0); backc<=min(c+2,C-1); backc++) {
											dp[r][c]=min(dp[r][c],dp[backr][backc]+1); //Magic check
											//Obstacles will be huge numbers, 
											//therefore no affect on final answer
										}
									}
								}			
							}
						}
					}
				}
				for (int r = 0; r < R; r++) { //Full matrix check after intermediate values were 
					//calculated
		 			for (int c = 0; c < C; c++) {
						if (grid[r][c]=='.') {
							if (r>0) dp[r][c]=min(dp[r][c],dp[r-1][c]);
							if (c>0) dp[r][c]=min(dp[r][c],dp[r][c-1]);
							if (r+1<R) dp[r][c]=min(dp[r][c],dp[r+1][c]);
							if (c+1<C) dp[r][c]=min(dp[r][c],dp[r][c+1]);
							for (int backr = max(r-2,0); backr<=min(r+2,R-1); backr++) {
								for (int backc = max(c-2,0); backc<=min(c+2,C-1); backc++) {
									dp[r][c]=min(dp[r][c],dp[backr][backc]+1); //Magic check
									//Obstacles will be huge numbers, 
									//therefore no affect on final answer
								}
							}
						}			
					}
				}
				ans=min(ans,dp[r2][c2]);
			}
		}
		O.pln(ans>=Integer.MAX_VALUE?-1:ans);
	}
	public static long min(long a, long b) {return Math.min(a,b);}
	public static long max(long a, long b) {return Math.max(a,b);}
	public static int min(int a, int b) {return Math.min(a,b);}
	public static int max(int a, int b) {return Math.max(a,b);}
	public static long abs(long x, long y) {return Math.abs(x-y);}
	public static long ceil(long num, long den) {long ans = num/den; if (num%den!=0) 
	ans++; return ans;}
	public static long GCD(long a, long b) {
		if (a==0||b==0) return max(a,b);
		return GCD(max(a,b),max(a,b)%min(a,b));
	}
	public static long FastExp(long base, long exp, long mod) {
		long ans=1;
		while (exp>0) {
			if (exp%2==1) ans*=base;
			exp/=2;
			base*=base;
			base%=mod;
			ans%=mod;
		}
		return ans;
	}
	public static long ModInv(long num,long mod) {return FastExp(num,mod-2,mod);}
	public static int pop(long x) { //Returns number of bits within a number
		int cnt = 0;
		while (x>0) {
			if (x%2==1) cnt++;
			x/=2;
		}
		return cnt;
	}
	static class FastScanner {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st=new StringTokenizer("");
		String next() {
			while (!st.hasMoreTokens())
				try {
					st=new StringTokenizer(br.readLine());
				} catch (IOException e) {
					e.printStackTrace();
				}
			return st.nextToken();
		}
		int nextInt() {return Integer.parseInt(next());}
		long nextLong() {return Long.parseLong(next());};
		double nextDouble() {return Double.parseDouble(next());}
	}
	static class OutPut{
		PrintWriter w = new PrintWriter(System.out);
		void pln(double x) {w.println(x);w.flush();}
		void pln(boolean x) {w.println(x);w.flush();}
		void pln(int x) {w.println(x);w.flush();}
		void pln(long x) {w.println(x);w.flush();}
		void pln(String x) {w.println(x);w.flush();}
		void pln(char x) {w.println(x);w.flush();}
		void pln(StringBuilder x) {w.println(x);w.flush();}
		void pln(BigInteger x) {w.println(x);w.flush();}
		void p(int x) {w.print(x);w.flush();}
		void p(long x) {w.print(x);w.flush();}
		void p(String x) {w.print(x);w.flush();}
		void p(char x) {w.print(x);w.flush();}
		void p(StringBuilder x) {w.print(x);w.flush();}
		void p(BigInteger x) {w.print(x);w.flush();}
		void p(double x) {w.print(x);w.flush();}
		void p(boolean x) {w.print(x);w.flush();}
	}
}