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: Runtime Error)

import java.io.PrintWriter
import java.util.*
import java.math.*
import java.lang.*
import kotlin.comparisons.*

val pw = PrintWriter(System.out)
val MOD: Long = (1e+9 + 7).toLong()

fun printMap(map: Array<CharArray>) {
    map.forEach {
        println(it.toList())
    }
}
fun Char.toNum(): Int = this.toString().toInt()

fun main(args: Array<String>) {
    val (h, w) = readListOfInt()
    val (ch, cw) = readListOfInt()
    val (dh, dw) = readListOfInt()
    val map = Array(h+2) { CharArray(w+2) { '#' } }
    for(i in 1 .. h) {
        val row = ("#" + read() + "#").toCharArray()
        map[i] = row
    }

    var counter = '0' 
    val nexts = listOf(Pair(0, 1), Pair(0, -1), Pair(1,0), Pair(0,1))
    for(y in 1 .. h) {
        for(x in 1 .. w) {
            if(map[y][x] == '.') {
                val st = Stack<Pair<Int, Int>>()
                map[y][x] = counter 
                st.push(Pair(y, x))
                while(!st.isEmpty()) {
                    val cur = st.pop()
                    nexts.forEach { next ->
                        val ny = cur.first + next.first
                        val nx = cur.second + next.second
                        if(map[ny][nx] == '.') {
                            map[ny][nx] = counter
                            st.push(Pair(ny, nx))
                        }
                    }
                }
                counter++
            }
        }
    }
    val edges = Array(counter.toNum()) { mutableSetOf<Int>() }
    val warps = mutableListOf<Pair<Int, Int>>()
    for(i in -2 .. 2) {
        for(j in -2 .. 2) {
            if(i == 0 && j == 0) continue
            warps.add(Pair(i, j))
        }
    }
    // println(warps)
    // println(warps.size)
    for(y in 1 .. h) {
        for(x in 1 .. w) {
            if(map[y][x] != '#') {
                val cur = map[y][x]
                warps.forEach { warp ->
                    val ny = y + warp.first
                    val nx = x + warp.second
                    if(0 < ny && ny <= h && 0 < nx && nx <= w) {
                        val next = map[ny][nx]
                        if(next != '#') {
                            val ncur = cur.toNum()
                            val nnext = next.toNum()
                            if(ncur != nnext) {
                                edges[ncur].add(nnext)
                                edges[nnext].add(ncur)
                            }
                        }
                    }
                }
            }
        }
    }
    // printMap(map)
    // edges.forEachIndexed { i, it ->
    //     println("$i: $it")
    // }

    val start = map[ch][cw].toNum()
    val goal = map[dh][dw].toNum()
    val points = Array(counter.toNum()) { Long.MAX_VALUE }
    points[start] = 0
    val st = Stack<Pair<Int, Long>>() // cur, warp-num
    st.push(Pair(start, 0L))
    while(!st.isEmpty()) {
        val top = st.pop()
        val (cur, num) = top
        if(cur == goal) {
            points[goal] = Math.min(points[goal], num)
        }
        edges[cur].forEach { e ->
            if(num + 1 < points[e]) {
                points[e] = Math.min(points[e], num + 1)
                st.push(Pair(e, num + 1)) 
            }
        }
    }
    // println("points: ${points.toList()}")

    val ans = if(points[goal] == Long.MAX_VALUE) -1L else points[goal]
    println(ans)
	pw.flush()
}

/****** Declared Functions and Data Structures ******/
// IO
fun read() = readLine()!!
fun readInt() = read().toInt()
fun readLong() = read().toLong()
fun readDouble() = read().toDouble()
fun readListOfString() = read().split(" ")
fun readListOfInt() = readListOfString().map { it.toInt() }
fun readListOfLong() = readListOfString().map { it.toLong() }
fun readListOfDouble() = readListOfString().map { it.toDouble() }

fun Double.format(digits: Int) = String.format("%.${digits}f", this)
fun Float.format(digits: Int) = String.format("%.${digits}f", this)

fun print(value: Any) { pw.print(value) }
fun println(value : Any) { pw.println(value) }

// Extensions
fun<T> List<T>.toBuckets(): Map<T, Int>
	= this.groupBy { it }.mapValues { it.value.size }

fun<T: Comparable<T>> Array<T>.upperBound(element: T, fromIndex: Int=0, toIndex: Int=this.size): Int
	= this.toList().upperBound(element, fromIndex, toIndex)

fun<T: Comparable<T>> List<T>.upperBound(element: T, fromIndex: Int=0, toIndex: Int=this.size): Int {
	var l = fromIndex
	var r = toIndex
	while(l < r) {
		val mid = (l+r) / 2
		if(element >= this[mid]) { 
			l = mid + 1
		} else {
			r = mid
		}
	}
	return l
}

fun<T: Comparable<T>> Array<T>.lowerBound(element: T, fromIndex: Int=0, toIndex: Int=this.size): Int
	= this.toList().lowerBound(element, fromIndex, toIndex)

fun<T: Comparable<T>> List<T>.lowerBound(element: T, fromIndex: Int=0, toIndex: Int=this.size): Int {
	var l = fromIndex
	var r = toIndex
	while(l < r) {
		val mid = (l+r) / 2
		if(element > this[mid]) { 
			l = mid + 1
		} else {
			r = mid
		}
	}
	return r 
}

fun <K, V> Map<K, V>.toMutableMap(): MutableMap<K, V> = HashMap(this)

// Util Functions
fun Long.makeDivisors(): List<Long> {
	val divisors = mutableListOf<Long>()
	for(i in 1L .. Math.sqrt(this.toDouble()).toLong()+1L) {
		if(this % i == 0L) {
			divisors.add(i)
			if(i != this/i) {
				divisors.add(this/i)
			}
		}
	}
	return divisors.distinct().sorted()
}

fun Long.isPrime(): Boolean {
	if(this==1L) return false
	for(i in 2L .. Math.sqrt(this.toDouble()).toLong() + 1L) {
		if(this % i == 0L && this != i) {
			return false
		}
	}
	return true
}

fun Long.primeFactorize(): Map<Long, Int> {
	val map = mutableMapOf<Long, Int>()
	var num = this
	for(i in 2L .. Math.sqrt(num.toDouble()).toLong()+1L) {
		if(num % i == 0L) {
			while(num % i == 0L) {
				map[i] = (map[i]?:0) + 1
				num /= i
			}
		}
	}
	if(num != 1L) {
		map[num] = 1 
	}
	return map
}

fun<T> permutations(src: List<T>): List<List<T>> {
	if(src.size == 1) return listOf(src)
	val perms = mutableListOf<List<T>>()
	val insertElement = src[0]
	permutations(src.drop(1)).forEach { perm ->
		for(i in 0..perm.size) {
			val newPerm = perm.toMutableList()
			newPerm.add(i, insertElement)
			perms.add(newPerm.toList())
		}
	}
	return perms
}

// return nCr, if you want nCr, please access v[n][r]
fun combinations(n: Long): List<List<Long>> {
	val v = (0..n).map { (0..n).map{0L}.toMutableList() }.toMutableList()
	for(i in 0 until v.size) {
		v[i][0] = 1L
		v[i][i] = 1L
	}
	for(i in 0 until v.size) {
		for(j in 1 until i) {
			v[i][j] = (v[i-1][j-1] + v[i-1][j]) % MOD
		}
	}
	return v.map { it.toList() }.toList()
}

fun repeatedModPow(a: Long, n: Long, mod: Long): Long = 
	when {
		n == 0L -> 1L
		n == 1L -> a % mod
		n % 2L == 1L -> (a * repeatedModPow(a, n-1L, mod)) % mod
		else -> {
			val tmp = repeatedModPow(a, n / 2L, mod)
			(tmp * tmp) % mod
		}
	}

// return nCr % MOD
fun modnCkWithoutArray(n: Long, k: Long, mod: Long): Long {
	var ret = 1L
	val min = Math.min(k, n-k)
	// まず分母の計算
	for(i in n downTo (n - min + 1)) {
		ret = ret * i % mod
	}
	for(i in min downTo 1) {
		ret = ret * repeatedModPow(i, (mod - 2L), mod) % mod
	}
	return ret
}

// return nCr % MOD
fun modnCk(n: Int, k: Int, mod: Long): Long {
	val factorials = Array(n+1) { 0L }.apply {
		this[0] = 1L
		if(this.size > 1) this[1] = 1L
	}
	val inverses = Array(n+1) { 0L }.apply {
		this[0] = 1L
		if(this.size > 1) this[1] = 1L
	}
	val factorialInverses = Array(n+1) { 0L }.apply {
		this[0] = 1L
		if(this.size > 1) this[1] = 1L
	}
	for(i in 2 .. n) {
		factorials[i] = (factorials[i-1] * i.toLong() % mod)
		inverses[i] = (mod - inverses[mod.toInt() % i] * (mod / i.toLong()) % mod)
		factorialInverses[i] = (factorialInverses[i-1] * inverses[i] % mod)
	}

	return factorials[n] % mod * (factorialInverses[k] * factorialInverses[n-k] % mod) % mod
}

// should be a >= b
fun gcd(a: Long, b: Long): Long = 
	if(b == 0L) a else gcd(b, a % b)

// shoud be a >= b
fun lcm(a: Long, b: Long): Long = 
	a / gcd(a, b) * b

fun sumDigits(num_: Long): Long {
	var num = num_
	var rtn: Long = 0
	while(num != 0.toLong()) {
		val tmp = num % 10
		rtn += tmp
		num /= 10
	}
	return rtn
}

fun Double.isDecimal(): Boolean = ((this - Math.floor(this)) != 0.0)

// Data Structures

class UnionFind(private val n: Int) {
	private val parent: Array<Int> = Array(n) { 0 }
	private val rank: Array<Int> = Array(n) { 0 }
	private val size: Array<Int> = Array(n) { 0 }

	init {
		for(i in 0 until n) {
			parent[i] = i
			rank[i] = 1
			size[i] = 1
		}
	}

	fun union(u: Int, v: Int) {
		var x = root(u)
		var y = root(v)
		if(x != y) {
			if(rank[y] < rank[x]) {
				val tmp = y 
				y = x
				x = tmp 
			}
			parent[x] = y
			rank[y] += rank[x]
			rank[x] = -1
			val totalSize = size[x] + size[y]
			size[x] = totalSize
			size[y] = totalSize
		}
	}

	fun root(u: Int): Int {
		var x = u
		while(parent[x] != x) {
			x = parent[x]
		}
		return x 
	}

	fun size(u: Int): Int = size[root(u)]
}