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 Fortran (GNU Fortran 9.2.1) (judge verdict: Wrong Answer)

module mod_weighted_graph
  implicit none
  integer(8), parameter :: long_infty = lshift(1_8, 60)
  integer, parameter :: int_infty = lshift(1, 30)

  type t_edge
    integer :: from = 0
    integer :: to = 0
    integer :: capacity = 0
    integer :: reverse = 0
    integer(8) :: weight = 0
  end type

  type t_list
    type(t_edge), allocatable :: at(:)
  end type

  type weighted_graph
    type(t_list), allocatable :: list(:)
  contains
    procedure :: dijkstra => dijkstra
    procedure :: ford_fulkerson => ford_fulkerson
    procedure :: prim => prim
  end type

  type t_node
    type(t_node), private, pointer :: left => null(), right => null()
    integer :: rank = 1
    integer :: vertex, from
    integer(8) :: cost
  end type

  type leftist_heap
    integer :: size = 0
    type(t_node), private, pointer :: root => null()
  end type

  interface weighted_graph
    module procedure :: newwg0
  end interface weighted_graph

contains
  
  type(t_edge) function newe0(from, to, weight, capacity, reverse) result(res)
    integer, intent(in) :: from, to
    integer(8), intent(in) :: weight
    integer, optional, intent(in) :: capacity, reverse
    res%from = from
    res%to = to
    res%weight = weight
    if (present(capacity)) res%capacity = capacity
    if (present(reverse)) res%reverse = reverse
  end

  type(weighted_graph) function newwg0(n, m, a, b, weight, capacity, undirected) result(res)
    integer, intent(in) :: n, m, a(:), b(:)
    integer(8), intent(in) :: weight(:)
    integer, optional, intent(in) :: capacity(:)
    logical, optional, intent(in) :: undirected
    logical :: u, cap
    integer :: c(n), i
    u = merge(undirected, .true., present(undirected))
    cap = present(capacity)
    c = 0
    do i = 1, m
      c(a(i)) = c(a(i)) + 1
      if (cap) c(b(i)) = c(b(i)) + 1
      if (u) then
        c(b(i)) = c(b(i)) + 1
        if (cap) c(a(i)) = c(a(i)) + 1
      end if
    end do
    allocate(res%list(n))
    do i = 1, n
      allocate(res%list(i)%at(c(i)))
    end do
    do i = m, 1, -1
      if (cap) then
        res%list(a(i))%at(c(a(i))) = newe0(a(i), b(i), weight(i), capacity(i), c(b(i)))
        res%list(b(i))%at(c(b(i))) = newe0(b(i), a(i), weight(i), 0, c(a(i)))
        c(a(i)) = c(a(i)) - 1
        c(b(i)) = c(b(i)) - 1
      else
        res%list(a(i))%at(c(a(i))) = newe0(a(i), b(i), weight(i))
        c(a(i)) = c(a(i)) - 1
      end if
      if (u) then
        if (cap) then
          res%list(b(i))%at(c(b(i))) = newe0(b(i), a(i), weight(i), capacity(i), c(a(i)))
          res%list(a(i))%at(c(a(i))) = newe0(a(i), b(i), weight(i), 0, c(b(i)))
          c(a(i)) = c(a(i)) - 1
          c(b(i)) = c(b(i)) - 1
        else
          res%list(b(i))%at(c(b(i))) = newe0(b(i), a(i), weight(i))
          c(b(i)) = c(b(i)) - 1
        end if
      end if
    end do
  end

  logical function less(a, b) result(res)
    type(t_node), pointer, intent(in) :: a, b
    res = a%cost < b%cost
  end

  subroutine swap(a, b)
    type(t_node), pointer, intent(inout) :: a, b
    type(t_node), pointer :: c
    c => a
    a => b
    b => c
  end

  function newn0(vertex, cost) result(res)
    integer, intent(in) :: vertex
    integer(8), intent(in) :: cost
    type(t_node), pointer :: res
    res => null()
    allocate(res)
    res%vertex = vertex
    res%cost = cost
  end

  recursive function meld_node(a, b) result(res)
    type(t_node), pointer, intent(in) :: a, b
    type(t_node), pointer :: res
    logical :: f
    if (.not.associated(a)) then
      res => b; return
    end if
    if (.not.associated(b)) then
      res => a; return
    end if
    if (less(a, b)) then
      res => a
      res%right => meld_node(res%right, b)
    else
      res => b
      res%right => meld_node(res%right, a)
    end if
    f = .not.associated(res%left)
    if (.not.f) f = res%left%rank < res%right%rank
    if (f) call swap(res%left, res%right)
    res%rank = merge(res%right%rank, 0, associated(res%right)) + 1
  end

  function poll(this) result(res)
    class(leftist_heap), intent(inout) :: this
    type(t_node), pointer :: res
    res => this%root
    this%root => meld_node(this%root%left, this%root%right)
    this%size = this%size - 1
  end

  subroutine offer(this, vertex, cost, from)
    class(leftist_heap), intent(inout) :: this
    integer, intent(in) :: vertex
    integer(8), intent(in) :: cost
    integer, intent(in), optional :: from
    type(t_node), pointer :: node
    node => newn0(vertex, cost)
    if (present(from)) node%from = from
    this%root => meld_node(this%root, node)
    this%size = this%size + 1
  end

  function dijkstra(this, start) result(res)
    class(weighted_graph), intent(in) :: this
    integer, intent(in) :: start
    integer :: i, v
    integer(8) :: res(size(this%list)), cost
    type(t_node), pointer :: node
    type(leftist_heap) :: pq
    type(t_edge) :: e
    res = long_infty
    res(start) = 0
    call offer(pq, start, res(start))
    do while (pq%size > 0)
      node => poll(pq)
      v = node%vertex
      cost = node%cost
      deallocate(node)
      if (cost > res(v)) cycle
      do i = 1, size(this%list(v)%at)
        e = this%list(v)%at(i)
        if (res(e%to) > res(v) + e%weight) then
          res(e%to) = res(v) + e%weight
          call offer(pq, e%to, res(e%to))
        end if
      end do
    end do
  end

  integer function ford_fulkerson(this, start, goal) result(res)
    class(weighted_graph), intent(inout) :: this
    integer, intent(in) :: start, goal
    integer :: dflow
    logical :: used(size(this%list))
    res = 0
    do
      used = .false.
      dflow = ffdfs(this, used, start, goal, int_infty)
      if (dflow == 0) return
      res = res + dflow
    end do
  end

  recursive integer function ffdfs(this, used, u, goal, dflow) result(res)
    class(weighted_graph), intent(inout) :: this
    logical, intent(inout) :: used(:)
    integer, intent(in) :: u, goal
    integer, intent(in) :: dflow
    integer :: i, v, capacity, r
    if (u == goal) then
      res = dflow
      return
    end if
    used(u) = .true.
    do i = 1, size(this%list(u)%at)
      v = this%list(u)%at(i)%to
      capacity = this%list(u)%at(i)%capacity
      if (used(v) .or. capacity <= 0) cycle
      res = ffdfs(this, used, v, goal, min(dflow, capacity))
      r = this%list(u)%at(i)%reverse
      if (res > 0) then
        this%list(u)%at(i)%capacity = this%list(u)%at(i)%capacity - res
        this%list(v)%at(r)%capacity = this%list(v)%at(r)%capacity + res
        return
      end if
    end do
    res = 0
  end

  integer(8) function bellman_ford(n, m, a, b, weight, start, goal) result(res)
    integer, intent(in) :: n, m, a(:), b(:), start, goal
    integer(8), intent(in) :: weight(:)
    type(weighted_graph) :: gs, gg
    logical :: useds(n), usedg(n), changed
    integer :: i, u, v, cnt, x(m), y(m), step
    integer(8) :: w(m), cost(n)
    gs = newwg0(n, m, a, b, weight, undirected = .false.)
    gg = newwg0(n, m, b, a, weight, undirected = .false.)
    useds = .false.
    usedg = .false.
    call bfdfs(gs, useds, start)
    call bfdfs(gg, usedg, goal)
    cnt = 0
    do i = 1, m
      u = a(i)
      v = b(i)
      if (useds(u) .and. useds(v) .and. usedg(u) .and. usedg(v)) then
        cnt = cnt + 1
        x(cnt) = u
        y(cnt) = v
        w(cnt) = weight(i)
      end if
    end do
    cost = long_infty
    cost(start) = 0
    res = long_infty
    step = 0
    changed = .true.
    do while (changed)
      changed = .false.
      do i = 1, cnt
        if (cost(y(i)) > cost(x(i)) + w(i)) then
          cost(y(i)) = cost(x(i)) + w(i)
          changed = .true.
        end if
      end do
      step = step + 1
      if (step > n) then
        res = -long_infty; exit
      end if
    end do
    if (res == long_infty) res = cost(goal)
  end

  recursive subroutine bfdfs(this, used, u)
    type(weighted_graph), intent(in) :: this
    logical, intent(inout) :: used(:)
    integer, intent(in) :: u
    integer :: i, v
    used(u) = .true.
    do i = 1, size(this%list(u)%at)
      v = this%list(u)%at(i)%to
      if (used(v)) cycle
      call bfdfs(this, used, v)
    end do
  end

  type(weighted_graph) function prim(this) result(res)
    class(weighted_graph), intent(in) :: this
    logical :: used(size(this%list))
    integer :: i, v, from, a(size(this%list) - 1), b(size(this%list) - 1), cnt
    integer(8) :: cost, weight(size(this%list) - 1)
    type(t_node), pointer :: node
    type(leftist_heap) :: pq
    type(t_edge) :: e
    do i = 1, size(this%list(1)%at)
      e = this%list(1)%at(i)
      call offer(pq, e%to, e%weight, 1)
    end do
    used = .false.
    used(1) = .true.
    cnt = 0
    do while (pq%size > 0)
      node => poll(pq)
      v = node%vertex
      from = node%from
      cost = node%cost
      deallocate(node)
      if (used(v)) cycle
      used(v) = .true.
      cnt = cnt + 1
      a(cnt) = from
      b(cnt) = v
      weight(cnt) = cost
      do i = 1, size(this%list(v)%at)
        e = this%list(v)%at(i)
        if (used(e%to)) cycle
        call offer(pq, e%to, e%weight, v)
      end do
    end do
    res = newwg0(size(this%list), size(this%list) - 1, a, b, weight)
  end

end module mod_weighted_graph
program wizard_in_maze
  use mod_weighted_graph
  implicit none
  integer :: h, w, xs, ys, xg, yg, i, j, k, n = 0, cnt = 0
  integer :: g(-10:1010, -10:1010) = -1
  integer :: dx(4) = (/0, 1, 0, -1/)
  integer :: dy(4) = (/1, 0, -1, 0/)
  character(1000) :: s = ''
  logical, allocatable :: u(:), v(:)
  logical :: z(0:1001, 0:1001) = .false.
  integer, allocatable :: a(:), b(:)
  integer(8), allocatable :: d(:)
  type(weighted_graph) :: graph
  read(*,*) h, w
  read(*,*) xs, ys
  read(*,*) xg, yg
  g(1:h, 1:w) = 0
  do i = 1, h
    read(*,*) s
    do j = 1, w
      if (s(j:j) == '#') g(i, j) = -1
    end do
  end do
  do i = 1, h
    do j = 1, w
      if (g(i, j) == 0) then
        n = n + 1
        call dfs1(i, j, n)
      end if
    end do
  end do
  allocate(u(n), v(n))
  v = .false.
  do i = 1, h
    do j = 1, w
      if (g(i, j) < 0) cycle
      if (v(g(i, j))) cycle
      v(g(i, j)) = .true.
      u = .false.
      call dfs2(i, j)
      do k = 1, n
        if (k /= g(i, j) .and. u(k)) cnt = cnt + 1
      end do
    end do
  end do
  allocate(a(cnt), b(cnt), d(max(n, cnt)))
  cnt = 0
  v = .false.
  do i = 1, h
    do j = 1, w
      if (g(i, j) < 0) cycle
      if (v(g(i, j))) cycle
      v(g(i, j)) = .true.
      u = .false.
      call dfs2(i, j)
      do k = 1, n
        if (k /= g(i, j) .and. u(k)) then
          cnt = cnt + 1
          a(cnt) = g(i, j)
          b(cnt) = k
        end if
      end do
    end do
  end do
  d = 1_8
  graph = weighted_graph(n, cnt, a, b, d, undirected = .true.)
  d(1:n) = graph%dijkstra(g(xs, ys))
  write(*,'(i0)') merge(-1_8, d(g(xg, yg)), d(g(xg, yg)) == long_infty)
contains
  recursive subroutine dfs1(x0, y0, n)
    integer, intent(in) :: x0, y0, n
    integer :: x, y, i
    g(x0, y0) = n
    do i = 1, 4
      x = x0 + dx(i)
      y = y0 + dy(i)
      if (g(x, y) == 0) call dfs1(x, y, n)
    end do
  end
  recursive subroutine dfs2(x0, y0)
    integer, intent(in) :: x0, y0
    integer :: x, y, i
    z(x0, y0) = .true.
    do x = x0 - 2, x0 + 2
      do y = y0 - 2, y0 + 2
        if (g(x, y) > 0) u(g(x, y)) = .true.
      end do
    end do
    do i = 1, 4
      x = x0 + dx(i)
      y = y0 + dy(i)
      if (.not.z(x, y) .and. g(x, y) > 0) call dfs2(x, y)
    end do
  end
end program wizard_in_maze