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 Kotlin (1.3.71) (judge verdict: Accepted)

import kotlin.math.min

fun main() = abc176d()

@OptIn(ExperimentalStdlibApi::class)
fun abc176d() = IO_abc176d().exec {
    val (h, w) = readInt() to readInt()
    val (startY, startX) = readInt() - 1 to readInt() - 1
    val (goalY, goalX) = readInt() - 1 to readInt() - 1
    val grid = Array(h) { readString().map { it == '.' }.toBooleanArray() }

    data class Q(val y: Int, val x: Int, val warpCount: Long)

    val queue = ArrayDeque<Q>()
    val around = listOf(-1 to 0, 1 to 0, 0 to -1, 0 to 1)
    val mins = Array(h) { LongArray(w) { Long.MAX_VALUE / 100 } }

    queue.add(Q(startY, startX, 0))

    while (queue.isNotEmpty()) {
        val (currY, currX, currWarpCount) = queue.removeFirst()

        if (currY == goalY && currX == goalX) return@exec println(currWarpCount)
        if (currWarpCount >= mins[currY][currX]) continue
        mins[currY][currX] = min(mins[currY][currX], currWarpCount)

        for ((addY, addX) in around) {
            val nextY = currY + addY
            val nextX = currX + addX
            if (nextY in 0 until h && nextX in 0 until w && grid[nextY][nextX] && currWarpCount < mins[nextY][nextX]) {
                queue.addFirst(Q(nextY, nextX, currWarpCount))
            }
        }

        for (nextY in (currY - 2..currY + 2)) {
            for (nextX in (currX - 2..currX + 2)) {
                if (nextY == currY && nextX == currX || nextY !in 0 until h || nextX !in 0 until w) continue
                if (grid[nextY][nextX] && currWarpCount + 1 < mins[nextY][nextX]) {
                    queue.addLast(Q(nextY, nextX, currWarpCount + 1))
                }
            }
        }
    }

    println(-1)
}

// region kokokara template dayo (^o^)
@Suppress("unused", "ClassName", "SpellCheckingInspection", "ConvertToStringTemplate", "MemberVisibilityCanBePrivate")
private class IO_abc176d(private val separator: String = System.lineSeparator()) {
    private val input = System.`in`
    private val buffer = ByteArray(1024)
    private var pointer = 0
    private var bufferLength = 0
    private val sb = StringBuilder()
    private fun Byte.isPrintable() = this in 33..126
    private fun Byte.isNumeric() = this in '0'.toByte()..'9'.toByte()
    private fun Byte.toNumVal() = if (this.isNumeric()) this - '0'.toByte() else error("$this is not numeric")

    private fun hasNextByte(): Boolean {
        return if (pointer < bufferLength) true else {
            pointer = 0
            bufferLength = input.read(buffer)
            bufferLength > 0
        }
    }

    private fun readByte(): Byte = if (hasNextByte()) buffer[pointer++] else -1
    private fun skipUnprintable() = run { while (hasNextByte() && !buffer[pointer].isPrintable()) pointer++ }
    private fun hasNext(): Boolean = run { skipUnprintable() }.run { hasNextByte() }
    private fun hasNextOrError() = if (!hasNext()) error("has no next element.") else Unit

    fun readString(): String {
        hasNextOrError()
        val sb = StringBuilder()
        var b = readByte()
        while (b.isPrintable()) {
            sb.appendCodePoint(b.toInt())
            b = readByte()
        }
        return sb.toString()
    }

    fun readLong(): Long {
        hasNextOrError()
        var n = 0L
        var negative = false
        var b = readByte()
        if (b == '-'.toByte()) {
            negative = true
            b = readByte()
        }
        if (!b.isNumeric()) error("$b is not numeric.")
        while (true) {
            when {
                b.isNumeric() -> n = n * 10 + b.toNumVal()
                b.toInt() == -1 || !b.isPrintable() -> return if (negative) -n else n
                else -> error("failed to parse. [n=$n, b=$b]")
            }
            b = readByte()
        }
    }

    fun readInt() = readLong()
        .let { if (it in Int.MIN_VALUE..Int.MAX_VALUE) it.toInt() else error("$it is not in range of Int.") }

    fun readDouble(): Double {
        var n = 0.0
        var div = 1.0
        var negative = false
        var b = readByte()
        if (b == '-'.toByte()) {
            negative = true
            b = readByte()
        }
        do n = n * 10 + b.toNumVal()
        while (run { b = readByte() }.run { b.isNumeric() })
        if (b == '.'.toByte()) {
            while (run { b = readByte() }.run { b.isNumeric() })
                n += b.toNumVal() / (run { div *= 10 }.run { div })
        }
        return if (negative) -n else n
    }

    fun println(): Unit = run { sb.append(separator) }
    fun print(any: Any): Unit = run { sb.append(any) }
    fun println(any: Any): Unit = run { sb.append(any.toString() + separator) }
    fun flush() = run { kotlin.io.println(sb); sb.clear() }

    fun exec(action: IO_abc176d.() -> Unit) {
        var t: Throwable? = null
        Thread(null, { action() }, "solve", 128 * 1024 * 1024)
            .apply { setUncaughtExceptionHandler { _, t1 -> t = t1 } }
            .apply { start() }.join()
        t?.let { throw it }
        kotlin.io.print(sb)
    }

    fun readLine(): Nothing = error("readLine is disabled.")
}
// endregion kokomade template dayo (^o^)