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 C# (.NET Core 3.1.201) (judge verdict: Time Limit Exceeded)

using System;
using System.Numerics;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace debug
{
    class main
    {
        static void Main(string[] args)
        {
            //問題クラスを展開
            ProgramD a = new ProgramD();
            a.main();//実行する

        }

    }
    //ABC175
    class ProgramA
    {
        public void main()
        {
            //入力
            string[] s = Console.ReadLine().Split(' ');
            long n = long.Parse(s[0]);
            long x = long.Parse(s[1]);
            long t = long.Parse(s[2]);
            //30以上ならYes、それ以外はNoを出力
            if(n % x == 0)
                Console.WriteLine(n / x * t);
            else
                Console.WriteLine((n / x+1) * t);


        }
    }

    class ProgramB
    {
        public void main()
        {
            //入力

            string s = Console.ReadLine();

            long count = 0;
            for (int k = 0; k < s.Length; k++)
                count += s[k] - '0';

            //答え出力
            if(count % 9  == 0)
                Console.WriteLine("Yes");
            else
                Console.WriteLine("No");

        }
    }

    class ProgramC
    {
        public void main()
        {

            //入力
            long n = long.Parse(Console.ReadLine());
            string[] s = Console.ReadLine().Split(' ');

            long count = 0;
            long min = long.Parse(s[0]);
            for(int i = 1;i < n;i++)
            {
                long temp = long.Parse(s[i]);
                if(temp < min)
                {
                    count += min - temp;
                }
                else
                {
                    min = temp;
                }

            }

            Console.WriteLine(count);


        }
    }

    class ProgramD
    {
        public void main()
        {
            string[] a = Console.ReadLine().Split(' ');
            long r = long.Parse(a[0]);
            long c = long.Parse(a[1]);
            string[] b = Console.ReadLine().Split(' ');
            long sx = long.Parse(b[0]);
            long sy = long.Parse(b[1]);
            string[] e = Console.ReadLine().Split(' ');
            long gx = long.Parse(e[0]);
            long gy = long.Parse(e[1]);

            long[,] maze = new long[r, c];
            long[,] w = new long[r, c];

            //迷路作成
            for (long i = 0; i < r; i++)
            {
                string d = Console.ReadLine();
                for (int j = 0; j < c; j++)
                {
                    if (d[j] == '#')
                        maze[i, j] = 0;
                    else
                        maze[i, j] = 1;

                }

            }

            for (int i = 0; i < r; i++)
                for (int j = 0; j < c; j++)
                    w[i, j] = 1000000000;

            //キューを用意
            Queue<long> qx = new Queue<long>();
            Queue<long> qy = new Queue<long>();
            Queue<long> ww = new Queue<long>();
            List<long> ans = new List<long>();

            //スタートを入れる
            qx.Enqueue(sx - 1);
            qy.Enqueue(sy - 1);
            ww.Enqueue(0);
            maze[sx - 1, sy - 1] = -1;
            w[sx - 1, sy - 1] = 0;

            while (qx.Count != 0)
            {
                long num = qx.Count;
                for (long i = 0; i < num; i++)
                {
                    long tx = qx.Dequeue();
                    long ty = qy.Dequeue();
                    long wnum = ww.Dequeue();

                    if (tx == gx - 1 && ty == gy - 1)
                    {
                        maze[tx, ty] = Math.Min(maze[tx, ty], wnum);
                        continue;
                    }

                    if (w[tx, ty] < wnum)
                        continue;

                    for (long x = -2; x <= 2; x++)
                        for (long y = -2; y <= 2; y++)
                        {
                            long karix = tx - x;
                            long kariy = ty - y;

                            if (x == 0 && y == 0)
                                continue;

                            if (0 <= karix && karix < r && 0 <= kariy && kariy < c)
                            {

                                if (maze[karix, kariy] == 1)
                                {
                                    if (Math.Abs(x) + Math.Abs(y) == 1)
                                    {
                                        if (wnum < w[karix, kariy])
                                        {
                                            qx.Enqueue(karix);
                                            qy.Enqueue(kariy);
                                            ww.Enqueue(wnum);
                                            w[karix, kariy] = wnum;
                                        }
                                    }
                                    else
                                    {
                                        if (wnum + 1 < w[karix, kariy])
                                        {
                                            qx.Enqueue(karix);
                                            qy.Enqueue(kariy);
                                            ww.Enqueue(wnum + 1);
                                            w[karix, kariy] = wnum + 1;
                                        }

                                    }

                                }
                            }
                        }

                }

            }

            if(w[gx -1,gy-1] == 1000000000)
                Console.WriteLine(-1);
            else
                Console.WriteLine(w[gx - 1, gy - 1]);
        }
    }

    class ProgramE
    {

        public void main()
        {
            //入力
            string[] s = Console.ReadLine().Split(' ');
            long n = long.Parse(s[0]);
            long k = long.Parse(s[1]);

            long[] a = new long[n];

            string[] t = Console.ReadLine().Split(' ');

            for(int i = 0;i < n;i++)
                a[i] = long.Parse(t[i]);

            long min = 0;//最初を0にすると1に答えができる
            long max = 1000000000;//答候補の最大

            //二分探索（答えを決め打ちして、切る回数を数える。k回以下ならmax,そうでないならmin)
            //小さくした方が回数がかかるので、maxが満たす最小の丸太の長さ
            while(min + 1 != max)
            {
                long temp = (min + max) / 2;
                long cut = 0;
                //切る回数を数える
                for (int i = 0; i < n; i++)
                {
                    //tempが大きいなら切らない
                    if (a[i] < temp)
                        continue;
                    //割り切れるかどうかで回数は変わる
                    if(a[i] % temp == 0)
                        cut += a[i] / temp - 1;
                    else
                        cut += a[i] / temp;
                }

                //k回以下ならmax更新、そうでないならminを更新
                if (cut <= k)
                    max = temp;
                else
                    min = temp;

            }

            //答え出力
            Console.WriteLine(max);

        }


    }

}