Hard
In an n*n grid, there is a snake that spans 2 cells and starts moving from the top left corner at (0, 0) and (0, 1). The grid has empty cells represented by zeros and blocked cells represented by ones. The snake wants to reach the lower right corner at (n-1, n-2) and (n-1, n-1).
In one move the snake can:
(r, c) and (r, c+1) to (r, c) and (r+1, c).
(r, c) and (r+1, c) to (r, c) and (r, c+1).
Return the minimum number of moves to reach the target.
If there is no way to reach the target, return -1.
Example 1:

Input:
grid = [ [0,0,0,0,0,1],
[1,1,0,0,1,0],
[0,0,0,0,1,1],
[0,0,1,0,1,0],
[0,1,1,0,0,0],
[0,1,1,0,0,0]]
Output: 11
Explanation: One possible solution is [right, right, rotate clockwise, right, down, down, down, down, rotate counterclockwise, right, down].
Example 2:
Input:
grid = [ [0,0,1,1,1,1],
[0,0,0,0,1,1],
[1,1,0,0,0,1],
[1,1,1,0,0,1],
[1,1,1,0,0,1],
[1,1,1,0,0,0]]
Output: 9
Constraints:
2 <= n <= 1000 <= grid[i][j] <= 1import java.util.LinkedList
import java.util.Objects
import java.util.Queue
class Solution {
fun minimumMoves(grid: Array<IntArray>): Int {
val n = grid.size
val visited = Array(n) { IntArray(n) }
val bq: Queue<IntArray> = LinkedList()
bq.offer(intArrayOf(0, 0, 1))
visited[0][0] = visited[0][0] or 1
var level = 0
while (bq.isNotEmpty()) {
val levelSize = bq.size
for (l in 0 until levelSize) {
val cur = bq.poll()
val xtail = Objects.requireNonNull(cur)[0]
val ytail = cur[1]
val dir = cur[2]
if (xtail == n - 1 && ytail == n - 2 && dir == 1) {
return level
}
val xhead = xtail + if (dir == 1) 0 else 1
val yhead = ytail + if (dir == 1) 1 else 0
if (dir == 2) {
if (ytail + 1 < n && grid[xtail][ytail + 1] != 1 && grid[xtail + 1][ytail + 1] != 1) {
if (visited[xtail][ytail] and 1 == 0) {
bq.offer(intArrayOf(xtail, ytail, 1))
visited[xtail][ytail] = visited[xtail][ytail] or 1
}
if (visited[xtail][ytail + 1] and 2 == 0) {
bq.offer(intArrayOf(xtail, ytail + 1, 2))
visited[xtail][ytail + 1] = visited[xtail][ytail + 1] or 2
}
}
if (xhead + 1 < n && grid[xhead + 1][yhead] != 1 && visited[xhead][yhead] and 2 == 0) {
bq.offer(intArrayOf(xhead, yhead, 2))
visited[xhead][yhead] = visited[xhead][yhead] or 2
}
} else {
if (xtail + 1 < n && grid[xtail + 1][ytail] != 1 && grid[xtail + 1][ytail + 1] != 1) {
if (visited[xtail][ytail] and 2 == 0) {
bq.offer(intArrayOf(xtail, ytail, 2))
visited[xtail][ytail] = visited[xtail][ytail] or 2
}
if (visited[xtail + 1][ytail] and 1 == 0) {
bq.offer(intArrayOf(xtail + 1, ytail, 1))
visited[xtail + 1][ytail] = visited[xtail + 1][ytail] or 1
}
}
if (yhead + 1 < n && grid[xhead][yhead + 1] != 1 && visited[xhead][yhead] and 1 == 0) {
bq.offer(intArrayOf(xhead, yhead, 1))
visited[xhead][yhead] = visited[xhead][yhead] or 1
}
}
}
level += 1
}
return -1
}
}