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 Lua (LuaJIT 2.1.0) (judge verdict: Accepted)

local read = setmetatable({}, {__index = function(t, k) local a = {} for i=1,#k do table.insert(a, '*'..string.sub(k, i, i)) end local r = io.read local u = table.unpack or unpack return function() return r(u(a)) end end})
read.N = function(N) local t={} for i=1,N do t[i]=read.n() end return t end
string.totable = function(s) local t={} local u=string.sub for i=1,#s do t[i] = u(s, i, i) end return t end
string.split = function(s) local t={} for w in string.gmatch(s, "[^%s]+") do table.insert(t, w) end return (table.unpack or unpack)(t) end
local function array(dimensi0n, default_val) assert(type(default_val) ~= 'table') local n=dimensi0n local m={}if default_val~=nil then m[1]={__index=function()return default_val end}end for i=2,n do m[i]={__index=function(p, k)local c=setmetatable({},m[i-1])rawset(p,k,c)return c end}end return setmetatable({},m[n])end
local function tostringxx(o, depth) depth = depth or 0 if depth > 10 then return "<too deep!>" end if o == _G then return "<_G>" end local indent0 = (" "):rep((depth) * 2) local indent1 = (" "):rep((depth+1) * 2) local indent2= (" "):rep((depth+2) * 2) if type(o) == 'table' then local keys = {} local types = {} for k in pairs(o) do types[type(k)] = true table.insert(keys, k) end local types_count = 0 local lasttype for k in pairs(types) do types_count = types_count + 1 lasttype = k end if types_count == 1 and (lasttype == 'string' or lasttype == 'number') then table.sort(keys) end local inside = {} for i=1,#keys do local k = keys[i] local v = o[k] if type(k) == 'string' then k = string.format('%q', k) end table.insert(inside, indent1 .. '['..tostring(k)..'] = ' .. tostringxx(v, depth + 1)) end return '{\n' .. table.concat(inside, ',\n') .. '\n' .. indent0 .. '}' else if type(o) == 'string' then o = string.format('%q', o) end return tostring(o) end end
local function richtraceback() local x = 2 while true do local info = debug.getinfo(x) if not info then break end local fname = '<' .. info.short_src .. ":" .. info.linedefined .. ">" if info.name then fname = info.name end print(info.short_src .. ":" .. info.currentline .. ": in " .. ("%q"):format(fname)) print(" LOCALS:") local p = 1 while true do local name, val = debug.getlocal(x,p) if not name then break end print(" " .. name .. ": " .. tostringxx(val, 3)) p = p + 1 end print(" UPVALUES:") for p=1,info.nups do local name, val = debug.getupvalue(info.func,p) if not name then break end print(" " .. name .. ": " .. tostringxx(val, 3)) end x = x + 1 end end
local function myassert(b) if not b then richtraceback() error("assertion failed") end end 
--
-- heap
local Heap = {}
function Heap.new(upper_func)
    local self = setmetatable({}, {__index = Heap})
    self.a = {}
    self.upper_func = upper_func
    self.upper = function(k1, k2)
        assert(k1 < k2)
        if k1 == 0 then
            return false
        else
            return upper_func(self.a[k1], self.a[k2])
        end
    end
    self.lower = function(k1, k2)
        return not self.upper(k1, k2)
    end
    return self
end
 
function Heap:count()
    return #self.a
end
 
function Heap:_swap(k1, k2)
    local old_k1 = self.a[k1]
    self.a[k1] = self.a[k2]
    self.a[k2] = old_k1
end
 
function Heap:upheap(newk)
    local ku = math.floor(newk / 2)
    local k = newk
    while ku > 0 and self.lower(ku, k) do
        self:_swap(ku, k)
        k = math.floor(k/2)
        ku = math.floor(ku/2)
    end
end
 
function Heap:insertq(e)
    table.insert(self.a, e)
    self:upheap(#self.a)
end
 
function Heap:downheap(newk)
    local k = newk
    while k <= math.floor(#self.a/2) do
        local kdl = k*2
        local kdr = kdl + 1
        local kd
        if kdr <= #self.a and self.lower(kdl, kdr) then
            kd = kdr
        else
            kd = kdl
        end
        if self.upper(k, kd) then
            break
        end
        self:_swap(k, kd)
        k = kd
    end
end
 
function Heap:top()
    assert(#self.a >= 1)
    return self.a[1]
end
 
function Heap:remove_top()
    assert(#self.a >= 1)
    local v = self.a[1]
    self:_swap(1, #self.a)
    table.remove(self.a)
    self:downheap(1)
    return v
end
--------------------------------------
local K1 = 1000
local INF = math.floor(10^18)
--
local abs = math.abs
local floor = math.floor
--
local H, W = read.nn()
local Ch, Cw = read.nn()
local Dh, Dw = read.nnl()
local S = {}
for i=1,H do
    S[i] = read.l():totable()
end
local function isopen(h, w)
    return S[h] and S[h][w] == '.'
end
local function getid(h, w)
    return w + h * K1
end
local function gethw(id)
    local h, w = floor(id / K1), id % K1
    return h, w
end
local function make_tuple(id, weight)
    return {weight, id}
end
local function unpack_tuple(t)
    return t[1], t[2]
end

-- dijkstra's algorithm
local function find_mincost(srch, srcw, dsth, dstw)
    local srcid = getid(srch, srcw)
    local dstid = getid(dsth, dstw)
    local from_src = {} -- if v is unreachable, from_src[v] == nil.
    from_src[srcid] = 0
    local q = Heap.new(function (v1, v2)
        --local w1 = unpack_tuple(v1)
        --local w2 = unpack_tuple(v2)
        --return w1 < w2
        return v1[1] < v2[1]
    end)
    local finished = {}
    q:insertq(make_tuple(srcid, 0))
    while q:count() > 0 do
        local elem = q:remove_top()
        local cur_d, id = unpack_tuple(elem)
        if not finished[id] then
            finished[id] = true
            if id == dstid then
                return cur_d
            end
            local h, w = gethw(id)
            for dh=-2,2 do
                for dw=-2,2 do
                    if isopen(h+dh,w+dw) then
                        local aa = abs(dh)+abs(dw)
                        if aa == 0 then
                            -- 5x5 center
                        else
                            -- move A or B?
                            local step = (aa == 1) and 0 or 1
                            local toid = getid(h+dh,w+dw)
                            if not finished[toid] then
                                -- compare costs
                                local before = from_src[toid] or INF
                                local after = cur_d + step
                                if after < before then
                                    from_src[toid] = after
                                    q:insertq(make_tuple(toid, after))
                                end
                            end
                        end
                    end
                end
            end
        end
    end
    return -1
end

local cost = find_mincost(Ch, Cw, Dh, Dw)
print(cost)