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



Sample input:
4 4
1 1
4 4
..#.
..#.
.#..
.#..


Sample output:
1

Submission status: Accepted

Solution code:
class Grid:
    def __init__(self, H, W, grid, road_wall=(".", "#")):
        self.road, self.wall = road_wall
        self.H = H
        self.W = W
        self.grid = grid
        self.parent = [[-1] * self.W for _ in range(self.H)]
        self.move = [(1, 0), (-1, 0), (0, 1), (0, -1)]     # 動ける場所の候補
        self.move2 = dict()
        self.move2[(1,0)] = [(2,-1),(2,0),(2,1),(2,2),(1,1)]
        self.move2[(-1,0)] = [(-2,-1),(-2,0),(-2,1),(-2,-2),(-1,-1)]
        self.move2[(0,1)] = [(1,2),(0,2),(-1,2),(-2,2),(-1,1)]
        self.move2[(0,-1)] = [(1,-2),(0,-2),(-1,-2),(2,-2),(1,-1)]

    def bfs(self, start=(0,0), goal=-3, time=0, save=False):
        """
        :param start: スタート地点
        :param goal: ゴール地点
        :param save: True = 前回の探索結果を保持する
        :return: （ループがあっても）最短距離。存在しなければ -1
        """
        if save:
            parent = self.parent
        else:
            parent = [[-1] * self.W for _ in range(self.H)]
        p, t = start, time
        parent[p[0]][p[1]] = -2
        next_set = [(p, t)]
        broken_set = []
        while next_set:
            while next_set:
                p, t = next_set.pop()
                h, w = p
                for dh, dw in self.move:
                    q = (h + dh, w + dw)
                    if q[0] < 0 or q[0] >= self.H or q[1] < 0 or q[1] >= self.W:
                        continue
                    if parent[q[0]][q[1]] != -1:
                        continue
                    if self.grid[q[0]][q[1]] == self.wall:         # 壁があったら進まない
                        for dh2, dw2 in self.move2[(dh,dw)]:
                            r = (h + dh2, w + dw2)
                            broken_set.append((r, t))
                        continue
                    if q == goal:
                        return t
                    #### (debug code) ######
                    # self.debug(start, goal, q, t)
                    ########################
                    parent[q[0]][q[1]] = p
                    next_set.append((q, t))
            while broken_set:
                q, t = broken_set.pop()
                if q[0] < 0 or q[0] >= self.H or q[1] < 0 or q[1] >= self.W:
                    continue
                if parent[q[0]][q[1]] != -1:
                    continue
                if self.grid[q[0]][q[1]] == self.wall:  # 壁があったら進まない
                    continue
                if q == goal:
                    return t + 1
                parent[q[0]][q[1]] = 1
                next_set.append((q, t+1))
        return -1

    def debug(self, start, goal, p, t):
        player = p
        debug_grid = list(list(self.grid[h]) for h in range(self.H))
        if start != (None, None):
            debug_grid[start[0]][start[1]] = "S"
        if goal != -3:
            debug_grid[goal[0]][goal[1]] = "G"
        debug_grid[player[0]][player[1]] = "P"
        print("~~~~~~~~~ t = " + str(t + 1) + "  ~~~~~~~~")
        for debug_h in range(self.H):
            print("".join(str(debug_grid[debug_h][debug_w]) for debug_w in range(self.W)))


############################################################################################

import sys
input = sys.stdin.readline



road, wall = ".", "#"                         # (進行可能を意味する記号, 進行不可を意味する記号)

H, W = map(int,input().split())                # 左上は(h,w)=(0,0)、右下は(h,w)=(H-1,W-1)
x, y = map(int, input().split())
start = (x-1,y-1)
x, y = map(int, input().split())
goal = (x-1,y-1)
grid = []
for h in range(H):
    grid.append(input().rstrip())

g = Grid(H, W, grid, (road, wall))
res = g.bfs(start=start, goal=goal)
print(res)

Submission status: Accepted

Solution code:
from collections import defaultdict,deque

H, W = map(int, input().split())
S = list(map(int, input().split()))
G = list(map(int, input().split()))
S[0] -= 1
S[1] -= 1
G[0] -= 1
G[1] -= 1
c = [input() for i in range(H)]
dist = [[-1]*W for _ in range(H)]

for i in range(H):
    for g in range(W):
        if c[i][g] == "#":
            dist[i][g] = -2

checkList = set()
que = deque()
que.append(S)

directions = [(0, -1), (0, 1), (1, 0), (-1, 0)]

cost = 0

while True:
    if len(que) == 0:
        cost += 1
        que = set()
        for h, w in checkList:
            for i in range(-2, 3):
                for g in range(-2, 3):
                    nh = h+i
                    nw = w+g
                    if nw < 0 or nw > W-1 or nh < 0 or nh > H-1:
                        continue
                    else:
                        if dist[nh][nw] == -1:
                            que.add((nh, nw))
        que = deque(que)
        checkList = set()
        if len(que) == 0:
            print(-1)
            exit()
    else:
        h, w = que.popleft()
        dist[h][w] = cost
        if h == G[0] and w == G[1]:
            print(cost)
            exit()
        for i in range(4):
            nh = h+directions[i][0]
            nw = w+directions[i][1]
            if nw < 0 or nw > W-1 or nh < 0 or nh > H-1:
                continue
            if dist[nh][nw] == -1:
                que.append((nh, nw))
                dist[nh][nw] = cost
            elif dist[nh][nw] == -2:
                checkList.add((h, w))

Submission status: Accepted

Solution code:
# -*- coding: utf-8 -*-
#
import math
import sys

from collections import deque

h,w = map(int, input().split())

ch,cw = map(int, input().split())
dh,dw = map(int, input().split())

maze =["#"*(w+4) for i in range(2)] + ["##"+input()+"##" for i in range(h)] + ["#"*(w+4) for i in range(2)]
temp = [[-1]*(w+4) for i in range(h+4)]

#print(maze)

q = deque([(ch+1,cw+1)])
temp[ch+1][cw+1]=0

opt = [(0,1),(0,-1),(1,0),(-1,0)]

while q:
    y,x = q.popleft()
#    print(y,x)
    # aruki
    for i in opt:
        ty,tx = y+i[0], x+i[1]
        if maze[ty][tx]=='#':
            continue
        if (temp[ty][tx] == -1 or temp[ty][tx] > temp[y][x]):
            temp[ty][tx] = temp[y][x] # ikeru
            q.appendleft((ty,tx)) # new ikeru basho tuika
    # warp
    for i in range(-2,3):
        for j in range(-2,3):
            ty,tx = y+i, x+j
            if maze[ty][tx] == "#":
                continue
            if temp[ty][tx] == -1 or temp[ty][tx] > temp[y][x]+1:
                temp[ty][tx] =  temp[y][x]+1
                q.append((ty,tx))  # 
#    print(q)


print(temp[dh+1][dw+1])

Submission status: Accepted

Solution code:
class Grid:
    def __init__(self, H, W, grid, road_wall=(".", "#")):
        self.road, self.wall = road_wall
        self.H = H
        self.W = W
        self.grid = grid
        self.parent = [[-1] * self.W for _ in range(self.H)]
        self.move = [(1, 0), (-1, 0), (0, 1), (0, -1)]     # 動ける場所の候補
        self.move2 = dict()
        self.move2[(1,0)] = [(2,-1),(2,0),(2,1),(2,2),(1,1)]
        self.move2[(-1,0)] = [(-2,-1),(-2,0),(-2,1),(-2,-2),(-1,-1)]
        self.move2[(0,1)] = [(1,2),(0,2),(-1,2),(-2,2),(-1,1)]
        self.move2[(0,-1)] = [(1,-2),(0,-2),(-1,-2),(2,-2),(1,-1)]

    def bfs(self, start=(0,0), goal=-3, time=0, save=False):
        """
        :param start: スタート地点
        :param goal: ゴール地点
        :param save: True = 前回の探索結果を保持する
        :return: （ループがあっても）最短距離。存在しなければ -1
        """
        if save:
            parent = self.parent
        else:
            parent = [[-1] * self.W for _ in range(self.H)]
        p, t = start, time
        parent[p[0]][p[1]] = -2
        next_set = deque([(p, t)])
        broken_set = deque([])
        while next_set:
            while next_set:
                p, t = next_set.popleft()
                h, w = p
                for dh, dw in self.move:
                    q = (h + dh, w + dw)
                    if q[0] < 0 or q[0] >= self.H or q[1] < 0 or q[1] >= self.W:
                        continue
                    if parent[q[0]][q[1]] != -1:
                        continue
                    if self.grid[q[0]][q[1]] == self.wall:         # 壁があったら進まない
                        for dh2, dw2 in self.move2[(dh,dw)]:
                            r = (h + dh2, w + dw2)
                            broken_set.append((r, t))
                        continue
                    if q == goal:
                        return t
                    #### (debug code) ######
                    # self.debug(start, goal, q, t)
                    ########################
                    parent[q[0]][q[1]] = p
                    next_set.append((q, t))
            while broken_set:
                q, t = broken_set.popleft()
                if q[0] < 0 or q[0] >= self.H or q[1] < 0 or q[1] >= self.W:
                    continue
                if parent[q[0]][q[1]] != -1:
                    continue
                if self.grid[q[0]][q[1]] == self.wall:  # 壁があったら進まない
                    continue
                if q == goal:
                    return t + 1
                parent[q[0]][q[1]] = 1
                next_set.append((q, t+1))
        return -1

    def debug(self, start, goal, p, t):
        player = p
        debug_grid = list(list(self.grid[h]) for h in range(self.H))
        if start != (None, None):
            debug_grid[start[0]][start[1]] = "S"
        if goal != -3:
            debug_grid[goal[0]][goal[1]] = "G"
        debug_grid[player[0]][player[1]] = "P"
        print("~~~~~~~~~ t = " + str(t + 1) + "  ~~~~~~~~")
        for debug_h in range(self.H):
            print("".join(str(debug_grid[debug_h][debug_w]) for debug_w in range(self.W)))


############################################################################################

from collections import deque
import sys
input = sys.stdin.readline



road, wall = ".", "#"                         # (進行可能を意味する記号, 進行不可を意味する記号)

H, W = map(int,input().split())                # 左上は(h,w)=(0,0)、右下は(h,w)=(H-1,W-1)
x, y = map(int, input().split())
start = (x-1,y-1)
x, y = map(int, input().split())
goal = (x-1,y-1)
grid = []
for h in range(H):
    grid.append(input().rstrip())

g = Grid(H, W, grid, (road, wall))
res = g.bfs(start=start, goal=goal)
print(res)

Submission status: Accepted

Solution code:
from collections import defaultdict
import sys
H,W=map(int,input().split())
Ch,Cw=map(int,input().split())
Dh,Dw=map(int,input().split())
smat=[[x=="." for x in input()] for _ in range(H)]
#print(smat)

graph=defaultdict(list)
#graph[i]: iから出る道の[重み,行先]の辞書
for i in range(H):
  for j in range(W):
    if not smat[i][j]:
      continue
    
    for k in [-1,1]:
      if 0<=i+k<H and smat[i+k][j]:
        graph[i*W+j].append(((i+k)*W+j,0))
      if 0<=j+k<W and smat[i][j+k]:
        graph[i*W+j].append((i*W+j+k,0))

    for k1 in [-1,1]:
      for k2 in [-1,1]:
        if 0<=i+k1<H and 0<=j+k2<W and smat[i+k1][j+k2]:
          graph[i*W+j].append(((i+k1)*W+j+k2,1))

    for k in range(-2,3):
      if i-2>=0 and 0<=j+k<W and smat[i-2][j+k] :
        graph[i*W+j].append(((i-2)*W+j+k,1))
      if i+2<H and 0<=j+k<W and smat[i+2][j+k] :
        graph[i*W+j].append(((i+2)*W+j+k,1))
        
    for k in range(-1,2):
      if 0<=i+k<H and j-2>=0 and smat[i+k][j-2]:
        graph[i*W+j].append(((i+k)*W+j-2,1))
      if 0<=i+k<H and j+2<W and smat[i+k][j+2]:
        graph[i*W+j].append(((i+k)*W+j+2,1))

dist_mat=[-1]*(H*W)
queue=[(Ch-1)*W+Cw-1]
d=0
while queue:
  new_queue=set()

  while queue:
    u=queue.pop()
    if u==(Dh-1)*W+Dw-1:
      print(d)
      sys.exit(0)
    dist_mat[u]=d
    
    for v,w in graph[u]:
      if dist_mat[v]!=-1:
        continue
      if w==0:
        queue.append(v)
      else:
        new_queue.add(v)

  queue=list(new_queue)
  d+=1
#print(dist)

print(-1)

Submission status: Accepted

Solution code:
import sys
def MI(): return map(int,sys.stdin.readline().rstrip().split())
def LS2(): return list(sys.stdin.readline().rstrip())  #空白なし

H,W = MI()
sh,sw = MI()  # スタート
gh,gw = MI()  # ゴール
S = [['#']*(W+1)] + [['#'] + LS2() for i in range(H)]
directions1 = [(-1,0),(1,0),(0,-1),(0,1)]
directions2 = [(i,j) for i in range(-2,3) for j in range(-2,3)]

from collections import deque

# 01BFS

q = deque([(sh,sw)])
ans = [[-1]*(W+1) for _ in range(H+1)]
ans[sh][sw] = 0
while q:
    nh,nw = q.pop()
    for dh,dw in directions1:
        if 1 <= nh+dh <= H and 1 <= nw+dw <= W and S[nh+dh][nw+dw] == '.':
            if ans[nh+dh][nw+dw] == -1 or ans[nh+dh][nw+dw] > ans[nh][nw]:
                ans[nh+dh][nw+dw] = ans[nh][nw]
                q.append((nh+dh,nw+dw))
    for dh,dw in directions2:
        if 1 <= nh+dh <= H and 1 <= nw+dw <= W and S[nh+dh][nw+dw] == '.':
            if ans[nh+dh][nw+dw] == -1:
                ans[nh+dh][nw+dw] = ans[nh][nw] + 1
                q.appendleft((nh+dh,nw+dw))

print(ans[gh][gw])

Submission status: Accepted

Solution code:
from heapq import heapify, heappop, heappush
import sys
read = sys.stdin.read
readlines = sys.stdin.readlines
input = sys.stdin.readline

H, W = map(int, input().split())
Ch, Cw = map(int, input().split())
Dh, Dw = map(int, input().split())
Ch -= 1
Cw -= 1
Dh -= 1
Dw -= 1
S = [input().rstrip() for _ in [0]*H]

INF = 10**10
D = [[INF]*W for _ in [0]*H]
used = set()

q = []
heappush(q, (0, Ch*W+Cw))


while q:
    d, ij = heappop(q)
    i, j = divmod(ij, W)

    for di in range(-2, 3):
        for dj in range(-2, 3):
            if di == dj == 0:
                continue
            I = i+di; J = j+dj
            if 0 <= I < H and 0 <= J < W and S[I][J] == '.':
                if abs(di)+abs(dj) == 1:
                    if D[I][J] <= d:
                        continue
                    D[I][J] = d
                    heappush(q, (d, I*W+J))
                else:
                    if D[I][J] <= d+1:
                        continue
                    D[I][J] = d+1
                    heappush(q, (d+1, I*W+J))

ans = D[Dh][Dw]
print(ans if ans < INF else -1)

Submission status: Accepted

Solution code:
from queue import deque
from sys import stdin
from sys import setrecursionlimit
setrecursionlimit(10 ** 7)

h,w = map(int,stdin.readline().rstrip().split())
ch,cw = map(int,stdin.readline().rstrip().split())
dh,dw = map(int,stdin.readline().rstrip().split())
inf = 10**10

ch -= 1
cw -= 1
dh -= 1
dw -= 1

def main():
    li = [["" for i in range(w)]for j in range(h)]

    for i in range(h):
        s = stdin.readline().rstrip()
        for j in range(w):
            li[i][j] = s[j]

    que = deque()

    mx = []
    my = []

    for i in range(-2,3):
        for j in range(-2,3):
            if i == 0 and j == 0:
                continue
            mx.append(i)
            my.append(j)

    lin = [[inf for i in range(w)]for j in range(h)]
    lin[ch][cw] = 0#ここをスタートの座標に変えること
    que.append((ch,cw))#ここもスタートの座標に変えること

    dx = [1,0,-1,0]
    dy = [0,1,0,-1]

    while que:
        k = que.popleft()
        x = k[0]
        y = k[1]
        no_magic = set()#魔法を使わずに行ける

        for i,j in zip(dx,dy):
            nx = x + i
            ny = y + j

            if nx < 0 or nx >= h or ny < 0 or ny >= w:
                continue
            elif li[nx][ny] == "#":
                continue
            else:
                if lin[nx][ny] > lin[x][y]:
                    que.appendleft((nx,ny))
                    no_magic.add((nx,ny))
                    lin[nx][ny] = lin[x][y]# 直接行ける
        
        for i,j in zip(mx,my):
            nx = x + i
            ny = y + j

            if nx < 0 or nx >= h or ny < 0 or ny >= w:
                continue
            elif li[nx][ny] == "#":
                continue
            else:
                if lin[nx][ny] > lin[x][y]+1:
                    if (nx,ny) not in no_magic:
                        que.append((nx,ny))
                    lin[nx][ny] = lin[x][y]+1# 魔法を使っていける

    if lin[dh][dw] == inf:
        print(-1)
    else:
        print(lin[dh][dw])

if __name__ == "__main__":
    main()

Submission status: Accepted

Solution code:
h,w = map(int, input().split())
ch, cw = map(int, input().split())
ch -= 1
cw -= 1
dh,dw = map(int, input().split())
dh -= 1
dw -= 1

def trans(s):
    res = []
    for i in s:
        if i == '.':
            res.append(-1)
        else:
            res.append(-2)
    return res

def move(x,y,dq,dq_next):
    for ix,iy in [(x+1, y), (x-1, y), (x, y+1), (x, y-1)]:
        if ix > h-1 or ix < 0 or iy > w-1 or iy < 0:
            continue
        if (m[ix][iy] == -1) or (m[ix][iy] > m[x][y]):
            m[ix][iy] = m[x][y]
            dq.append((ix, iy))
    for ix, iy in [(x-2, y-2), (x-2, y-1), (x-2, y), (x-2, y+1), (x-2, y+2),
                        (x-1, y-2), (x-1, y-1), (x-1, y+1), (x-1, y+2),
                        (x, y-2), (x, y+2),
                        (x+1, y-2), (x+1, y-1), (x+1, y+1), (x+1, y+2),
                        (x+2, y-2), (x+2, y-1), (x+2, y), (x+2, y+1), (x+2, y+2)]:
        if ix > h-1 or ix < 0 or iy > w-1 or iy < 0:
            continue
        if m[ix][iy] == -1:
            m[ix][iy] = m[x][y] + 1
            dq_next.append((ix, iy))
            
m = [trans(input()) for _ in range(h)]

from collections import deque

m[ch][cw] = 0

def main():
    dq = deque()
    dq_next = deque()
    dq.append((ch,cw))
    while True:
        while len(dq)>0:
            xx, yy = dq.popleft()
            if xx == dh and yy == dw:
                return m[xx][yy]
            move(xx, yy, dq, dq_next)
        if len(dq_next) > 0:
            dq = dq_next.copy()
            dq_next = deque()
        else:
            return -1
          
print(main())

Submission status: Accepted

Solution code:
from collections import deque
import sys


mX = [0, 1, 0, -1]
mY = [1, 0, -1, 0]
zX = [2, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, -1, -1, -1, -1, -2, -2, -2, -2, -2]
zY = [2, 1, 0, -1, -2, 2, 1, -1, -2, 2, -2, 2, -2, 1, -1, 2, 1, 0, -1, -2]


def bfs(u, S, M, H, W):  # u 開始点

    q = deque()
    q.append(u)
    visited = deque()
    while q:
        while q:
            u = q.popleft()
            visited.append([u[0], u[1]])

            # 徒歩移動
            for i in range(4):
                nx, ny = u[0] + mX[i], u[1] + mY[i]

                if nx < 0 or H <= nx or ny < 0 or W <= ny or S[nx][ny] == "#":
                    continue

                if M[nx][ny] == -1 or M[nx][ny] > M[u[0]][u[1]]:  # state を確認
                    M[nx][ny] = M[u[0]][u[1]]  # 徒歩移動
                    q.append([nx, ny])
                    visited.append([nx, ny])



        # 魔法移動
        while visited:
            u = visited.popleft()
            for j in range(20):
                wx = u[0] + zX[j]
                wy = u[1] + zY[j]
                if wx < 0 or H <= wx or wy < 0 or W <= wy or S[wx][wy] == "#":
                    continue
                if M[wx][wy] == -1 or M[wx][wy] > M[u[0]][u[1]] + 1:  # state を確認
                    M[wx][wy] = M[u[0]][u[1]] + 1
                    q.append([wx, wy])


def main():

    H, W = map(int, sys.stdin.readline().rstrip().split())
    Ch, Cw = map(int, sys.stdin.readline().rstrip().split())
    Dh, Dw = map(int, sys.stdin.readline().rstrip().split())

    S = []
    for i in range(H):
        S.append(sys.stdin.readline().rstrip())

    M = [[-1 for _ in range(W)] for _ in range(H)]

    if S[Ch - 1][Cw - 1] == "#":
        print(-1)
        return

    M[Ch - 1][Cw - 1] = 0
    bfs([Ch - 1, Cw - 1], S, M, H, W)

    print(M[Dh - 1][Dw - 1])


main()

Submission status: Accepted

Solution code:
from heapq import heappush, heappop
import sys
input = sys.stdin.readline

h, w = map(int, input().split())
ch, cw = map(lambda x: int(x) - 1, input().split())
dh, dw = map(lambda x: int(x) - 1, input().split())
s = [input() for _ in range(h)]

INF = 10**10
cost = [[INF] * w for _ in range(h)]

dxy = [(0, +1, 0), (0, 0, +1), (0, -1, 0), (0, 0, -1)]
dxy += [(1, i, j) for i in [-2, 2] for j in range(-2, 3)]
dxy += [(1, i, j) for j in [-2, 2] for i in range(-1, 2)]
dxy += [(1, -1, -1), (1, -1, +1), (1, +1, -1), (1, +1, +1)]

q = [(0, ch, cw)]
cost[ch][cw] = 0
while q:
    c, x, y = heappop(q)
    if cost[x][y] < c:
        continue

    if x == dh and y == dw:
        break

    for c_, dx_, dy_ in dxy:
        nx = x + dx_
        ny = y + dy_
        nc = c + c_
        if nx < 0 or nx >= h or ny < 0 or ny >= w:
            continue
        if s[nx][ny] == '#':
            continue
        if cost[nx][ny] <= nc:
            continue
        cost[nx][ny] = nc
        heappush(q, (nc, nx, ny))

ans = -1 if cost[dh][dw] == INF else cost[dh][dw]
print(ans)
# print(*cost, sep='\n')

Submission status: Accepted

Solution code:
from collections import deque


def main():

    def f(hi, wi):
        return hi * w + wi

    h, w = map(int, input().split())
    sh, sw = map(int, input().split())
    gh, gw = map(int, input().split())

    s = [input() for _ in range(h)]
    INF = 10 ** 9

    sh -= 1
    sw -= 1
    gh -= 1
    gw -= 1

    dq = deque([f(sh, sw)])
    dist = [[INF] * w for _ in range(h)]
    dist[sh][sw] = 0

    while dq:
        i = dq.popleft()
        hi, wi = divmod(i, w)

        for dh in range(-2, 3):
            for dw in range(-2, 3):
                nh = hi + dh
                nw = wi + dw
                if 0 <= nh <= h - 1 and 0 <= nw <= w - 1 and s[nh][nw] == ".":
                    if abs(dh) + abs(dw) == 1:
                        if dist[hi][wi] < dist[nh][nw]:
                            dist[nh][nw] = dist[hi][wi]
                            dq.appendleft(f(nh, nw))
                    else:
                        if dist[hi][wi] + 1 < dist[nh][nw]:
                            dist[nh][nw] = dist[hi][wi] + 1
                            dq.append(f(nh, nw))

    ans = dist[gh][gw]
    if ans == INF:
        ans = -1

    print(ans)


if __name__ == "__main__":
    main()

Submission status: Accepted

Solution code:
#!/usr/bin/env python3
import sys
from collections import deque
sys.setrecursionlimit(10**6)
INF = 10 ** 9 + 1  # sys.maxsize # float("inf")
MOD = 10 ** 9 + 7


def debug(*x):
    print(*x, file=sys.stderr)


def solve(H, W, Ch, Cw, Dh, Dw, walkable):
    N = HEIGHT * WIDTH
    visited = [0] * N

    start = (Ch + 1) * WIDTH + (Cw + 1)
    goal = (Dh + 1) * WIDTH + (Dw + 1)
    toVisit = []
    toVisit.append(start)

    currentDistance = 0
    while True:
        nextJumpOrigin = []
        while toVisit:
            p = toVisit.pop()
            if p == goal:
                return currentDistance
            if visited[p]:
                continue

            visited[p] = 1
            nextJumpOrigin.append(p)
            for d in [-1, +1, -WIDTH, +WIDTH]:
                if walkable[p + d] and not visited[p + d]:
                    toVisit.append(p + d)

        # no continuous cell
        for origin in nextJumpOrigin:
            for dx in [-2, -1, 0, +1, +2]:
                for dy in [-WIDTH * 2, -WIDTH, 0, WIDTH, WIDTH * 2]:
                    p = origin + dx + dy
                    if not walkable[p]:
                        continue
                    if visited[p]:
                        continue
                    toVisit.append(p)

        currentDistance += 1
        if not toVisit:
            return -1


def readMap(H, W):
    global SENTINEL, HEIGHT, WIDTH
    SENTINEL = 2
    HEIGHT = H + SENTINEL * 2
    WIDTH = W + SENTINEL * 2
    data = [0] * (HEIGHT * WIDTH)
    ok = ord(".")
    for i in range(H):
        S = input().strip()
        y = (i + SENTINEL) * WIDTH
        for j in range(W):
            data[y + (j + SENTINEL)] = 1 if S[j] == ok else 0
    return data


def main():
    # parse input
    H, W = map(int, input().split())
    Ch, Cw = map(int, input().split())
    Dh, Dw = map(int, input().split())
    D = readMap(H, W)
    print(solve(H, W, Ch, Cw, Dh, Dw, D))


# tests
T1 = """
4 4
1 1
4 4
..#.
..#.
.#..
.#..
"""
TEST_T1 = """
>>> as_input(T1)
>>> main()
1
"""

T2 = """
4 4
1 4
4 1
.##.
####
####
.##.
"""
TEST_T2 = """
>>> as_input(T2)
>>> main()
-1
"""

T3 = """
4 4
2 2
3 3
....
....
....
....
"""
TEST_T3 = """
>>> as_input(T3)
>>> main()
0
"""

T4 = """
4 5
1 2
2 5
#.###
####.
#..##
#..##
"""
TEST_T4 = """
>>> as_input(T4)
>>> main()
2
"""


def _test():
    import doctest
    doctest.testmod()
    g = globals()
    for k in sorted(g):
        if k.startswith("TEST_"):
            doctest.run_docstring_examples(g[k], g)


def as_input(s):
    "use in test, use given string as input file"
    import io
    f = io.StringIO(s.strip())
    g = globals()
    g["input"] = lambda: bytes(f.readline(), "ascii")
    g["read"] = lambda: bytes(f.read(), "ascii")


input = sys.stdin.buffer.readline
read = sys.stdin.buffer.read

if sys.argv[-1] == "-t":
    print("testing")
    _test()
    sys.exit()

main()

Submission status: Accepted

Solution code:
from collections import deque

d = [(1, 0), (-1, 0), (0, 1), (0, -1)]
d_ = [-2, -1, 0, 1, 2]

h, w = map(int, input().split())
ch, cw = map(int, input().split())
dh, dw = map(int, input().split())
s = [input() for i in range(h)]
INF = 10 ** 6

ch, cw = ch - 1, cw - 1
dh, dw = dh - 1, dw - 1
used = [[INF] * w for i in range(h)]

used[ch][cw] = 0
val = 0
q = deque([(ch, cw, val)])
while q:
    i, j, val = q.popleft()
    if val > used[i][j]:
        continue
    val = used[i][j]

    for di, dj in d:
        nx_i, nx_j = i + di, j + dj
        if not(0 <= nx_i < h and 0 <= nx_j < w):
            continue
        elif s[nx_i][nx_j] == "#":
            continue
        elif used[nx_i][nx_j] > val:
                used[nx_i][nx_j] = val
                q.appendleft((nx_i, nx_j, val))

    for di in d_:
        for dj in d_:
            nx_i, nx_j = i + di, j + dj
            if not(0 <= nx_i < h and 0 <= nx_j < w):
                continue
            elif s[nx_i][nx_j] == "#":
                continue
            elif used[nx_i][nx_j] > val + 1:
                used[nx_i][nx_j] = val + 1
                q.append((nx_i, nx_j, val + 1))

if used[dh][dw] == INF:
    print(-1)
else:
    print(used[dh][dw])

Submission status: Accepted

Solution code:
import sys
sys.setrecursionlimit(500000) 
input = sys.stdin.readline
from collections import deque
H,W = map(int,input().split())
C = list(map(int,input().split()))
C[0] -= 1; C[1] -= 1
D = list(map(int,input().split()))
D[0] -= 1; D[1] -= 1
S = []; INF = float("inf")
for i in range(H):
  temp = str(input());temp =list(temp)
  S.append(temp)
#print(S)
reach = [[INF]*W for _ in range(H)]
reach[C[0]][C[1]] = 0
dxdy = [(1,0),(-1,0),(0,1),(0,-1)]
Q = deque([])
Q.append([C,0])
while Q:
  z, score = Q.popleft()
  x = z[0];y=z[1]
 
  for i in range(4):
    nx = x + dxdy[i][0]
    ny = y + dxdy[i][1]
    #print(nx,ny)
    if 0<=nx<H and 0<=ny<W and S[nx][ny] == "." and reach[nx][ny] > score:
      reach[nx][ny] = min(score,reach[nx][ny])
      u = [nx,ny]
      Q.appendleft([u,score])
  #print(reach)
 
  for i in range(5): #0~4
    for j in range(5):
      mx = x-2 + i
      my = y-2 + j
      if i == 2 and j == 2:
        continue
      if mx < 0 or mx >= H or my < 0 or my >= W or S[mx][my] == "#":
        continue
      if reach[mx][my] <= score+1: #すでにこのスコア以下でいける。
        continue
      reach[mx][my] = min(score+1,reach[mx][my])
      p = [mx,my]
      #print(v,p,"X")
      Q.append([p,score+1])
#dfs(C,0)
#print(reach)
#print(reach[D[0]][D[1]])
if reach[D[0]][D[1]] == INF:
  print(-1)
else:
  print(reach[D[0]][D[1]])

Submission status: Accepted

Solution code:
from heapq import heappush, heappop
import sys
input = sys.stdin.readline

h, w = map(int, input().split())
ch, cw = map(lambda x: int(x) - 1, input().split())
dh, dw = map(lambda x: int(x) - 1, input().split())
s = [input() for _ in range(h)]

INF = 10**10
cost = [[INF] * w for _ in range(h)]
dx = [+1, 0, -1, 0]
dy = [0, +1, 0, -1]
dxy2 = []
dxy2 += [(i, j) for i in [-2, 2] for j in range(-2, 3)]
dxy2 += [(i, j) for j in [-2, 2] for i in range(-1, 2)]
dxy2 += [(-1, -1), (-1, +1), (+1, -1), (+1, +1)]
q = [(0, ch, cw)]
cost[ch][cw] = 0
while q:
    c, x, y = heappop(q)
    if cost[x][y] < c:
        continue

    if x == dh and y == dw:
        break

    for k in range(4):
        nx = x + dx[k]
        ny = y + dy[k]
        if nx < 0 or nx >= h or ny < 0 or ny >= w:
            continue
        if s[nx][ny] == '#':
            continue
        if cost[nx][ny] <= c:
            continue
        cost[nx][ny] = c
        heappush(q, (c, nx, ny))

    for dx_, dy_ in dxy2:
        nx = x + dx_
        ny = y + dy_
        if nx < 0 or nx >= h or ny < 0 or ny >= w:
            continue
        if s[nx][ny] == '#':
            continue
        if cost[nx][ny] <= c + 1:
            continue
        cost[nx][ny] = c + 1
        heappush(q, (c + 1, nx, ny))

ans = -1 if cost[dh][dw] == INF else cost[dh][dw]
print(ans)
# print(*cost, sep='\n')

Submission status: Accepted

Solution code:
H, W = map(int, input().split())
C = list(map(lambda x: int(x) - 1, input().split()))
D = list(map(lambda x: int(x) - 1, input().split()))
S = [input() for _ in range(H)]
toGo = [[False if i != C[0] or j != C[1] else True for j in range(W)] for i in range(H)]
queue, mahou = [C], [C]
ans = 0

while True:
    tmp = queue.pop()
    mahou.append(tmp)
    dfs = [tmp]

    while len(dfs):
        a = dfs.pop()
        for move in [[0, 1], [0, -1], [1, 0], [-1, 0]]:
            hh, ww = a[0] + move[0], a[1] + move[1]
            if hh >= H or hh < 0 or ww >= W or ww < 0:
                continue

            if not toGo[hh][ww] and S[hh][ww] == '.':
                toGo[hh][ww] = True
                dfs.append([hh, ww])
                mahou.append([hh, ww])

    if toGo[D[0]][D[1]]:
        break

    flag = True
    if not len(queue):
        ans += 1
        for k in mahou:
            for i in range(-2, 3):
                for j in range(-2, 3):
                    h, w = i + k[0], j + k[1]
                    if h >= H or h < 0 or w >= W or w < 0:
                        continue

                    if not toGo[h][w] and S[h][w] == '.':
                        flag = False
                        toGo[h][w] = True
                        queue.append([h, w])
        mahou = []

        if flag:
            print(-1)
            exit()

print(ans)