Problem:


Score : 400 points

Problem Statement

Takahashi has a maze, which is a grid of H \times W squares with H horizontal rows and W vertical columns.

The square at the i-th row from the top and the j-th column is a "wall" square if S_{ij} is #, and a "road" square if S_{ij} is ..

From a road square, you can move to a horizontally or vertically adjacent road square.

You cannot move out of the maze, move to a wall square, or move diagonally.

Takahashi will choose a starting square and a goal square, which can be any road squares, and give the maze to Aoki.

Aoki will then travel from the starting square to the goal square, in the minimum number of moves required.

In this situation, find the maximum possible number of moves Aoki has to make.

Constraints

1 \leq H,W \leq 20

S_{ij} is . or #.

S contains at least two occurrences of ..

Any road square can be reached from any road square in zero or more moves.

Input

Input is given from Standard Input in the following format:

H W
S_{11}...S_{1W}
:
S_{H1}...S_{HW}

Output

Print the maximum possible number of moves Aoki has to make.

Sample Input 1

3 3
...
...
...

Sample Output 1

4

If Takahashi chooses the top-left square as the starting square and the bottom-right square as the goal square, Aoki has to make four moves.

Sample Input 2

3 5
...#.
.#.#.
.#...

Sample Output 2

10

If Takahashi chooses the bottom-left square as the starting square and the top-right square as the goal square, Aoki has to make ten moves.



Sample input:
3 3
...
...
...


Sample output:
4

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)]     # 動ける場所の候補

    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)])
        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 self.grid[q[0]][q[1]] == self.wall:         # 壁があったら進まない
                    continue
                if parent[q[0]][q[1]] != -1:
                    continue
                #### (debug code) ######
                # self.debug(start, goal, q, t)
                ########################
                if q == goal:
                    return t + 1
                parent[q[0]][q[1]] = p
                next_set.append((q, t + 1))
        return -1

    def connection_counter(self):
        """
        :return: 連結成分の個数。有効グラフではあまり意味がない。
        """
        cnt = 0
        self.parent = [[-1] * self.W for _ in range(self.H)]
        for h in range(self.H):
            for w in range(self.W):
                if self.parent[h][w] == -1:
                    cnt += 1
                    self.bfs(start=(h,w), save=True)
        return cnt

    def distance_list(self, start=(0,0), save=False):
        """
        :param start: スタート地点
        :return: スタート地点から各点への距離のリスト
        """
        dist = [[-1] * self.W for _ in range(self.H)]
        if save:
            parent = self.parent
        else:
            parent = [[-1] * self.W for _ in range(self.H)]
        p, t = start, 0
        parent[p[0]][p[1]] = -2
        dist[p[0]][p[1]] = 0
        next_set = deque([(p, t)])

        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 self.grid[q[0]][q[1]] == self.wall:         # 壁があったら進まない
                    continue
                if parent[q[0]][q[1]] != -1:
                    continue
                dist[q[0]][q[1]] = t + 1
                parent[q[0]][q[1]] = p
                next_set.append((q, t + 1))
        return dist

    def most_distant_point(self, start=(0, 0), save=False):
        """
        :param start:
        :return: start 地点から最も遠い点を ((h,w), 距離) として出力
        """
        res = (start, 0)
        temp = 0
        dist = self.distance_list(start, save=save)
        for h in range(self.H):
            for w in range(self.W):
                if dist[h][w] > temp:
                    temp = dist[h][w]
                    res = ((h, w), temp)
        return res

    def diameter(self, start=(0,0), save=False):
        """
        :return:　木の直系（最も離れた二頂点間の距離）を返す
        """
        p = self.most_distant_point(start, save=False)
        res = self.most_distant_point(start=p[0], save=save)
        return res[1]

    def diameter2(self):
        """
        :return:　連結ではない時に、最大の直系を返す
        """
        res = 0
        for h in range(self.H):
            for w in range(self.W):
                if self.grid[h][w] == self.road and self.parent[h][w] == -1:
                    temp = self.diameter(start=(h, w), save=False)
                    if temp > res:
                        res = temp
        return res

    def dfs(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)]
        move2 = [[marshal.loads(marshal.dumps(self.move)) for _ in range(self.W)] for _ in range(self.H)]

        p, t = start, time
        parent[p[0]][p[1]] = -2
        while True:
            if move2[p[0]][p[1]]:
                h, w = p
                dh, dw = move2[p[0]][p[1]].pop()
                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 self.grid[q[0]][q[1]] == self.wall:         # 壁があったら進まない
                    continue
                if q == parent[p[0]][p[1]]:
                    """ 逆流した時の処理 """
                    """"""""""""""""""""
                    continue
                if parent[q[0]][q[1]] != -1:
                    """ サイクルで同一点を訪れた時の処理 """
                    """"""""""""""""""""
                    continue
                #### (debug code) ######
                # self.debug(start, goal, q, t)
                # self.show_visited(start, goal, q, t, parent)
                ########################
                if q == goal:
                    """ ゴール時の処理"""
                    """"""""""""""""""""
                    return t + 1
                """ p から q への引継ぎ"""
                """"""""""""""""""""
                parent[q[0]][q[1]] = p
                p, t = q, t + 1
            else:
                if p == start and t == time:
                    break
                p_temp = p
                p, t = parent[p[0]][p[1]], t-1
                """ p から進める点がもう無い時の点 p における処理 """
                # parent[p_temp[0]][p_temp[1]] = -1
                # move2[p_temp[0]][p_temp[1]].extend(marshal.loads(marshal.dumps(self.move)))
                """"""""""""""""""""
                """ 点 p から親ノードに戻ってきた時の親ノードにおける処理 """
                """"""""""""""""""""
        return -1

    def dfs2(self, start=(0, 0), goal=-3, time=0):
        visited = [[-1] * self.W for _ in range(self.H)]
        p, t = start, time
        res = 0
        def rec(p, past_p, t, visited, res):
            h, w = p
            visited[p[0]][p[1]] = 1
            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 grid[q[0]][q[1]] == self.wall:
                    continue
                if q == past_p:
                    """ 逆流した時の処理 """
                    """"""""""""""""""""
                    continue
                if visited[q[0]][q[1]] == 1:
                    """ サイクルで同一点を訪れた時の処理 """
                    """"""""""""""""""""
                    continue
                """ (debug code) """
                # self.debug(start, goal, q, t)
                # self.show_visited(start, goal, q, t, visited)
                """"""""""""""""""""
                if q == goal:
                    """ ゴール時の処理"""
                    """"""""""""""""""""
                    return t+1
                res = max2(rec(q, p, t + 1, visited, res), t + 1)
            """ 帰り際の処置（壊した道を元に戻す等)"""
            # visited[p[0]][p[1]] = -1
            """"""""""""""""""""
            return res
        return rec(p, -1, t, visited, res)

    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)))

    def show_visited(self, start, goal, p, t, parent):
        player = p
        debug_grid = list(list(self.grid[h]) for h in range(self.H))
        for h in range(H):
            for w in range(W):
                if parent[h][w] != -1:
                    debug_grid[h][w] = "V"
        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
import marshal
input = sys.stdin.readline



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

H, W = map(int,input().split())                # 左上は(h,w)=(0,0)、右下は(h,w)=(H-1,W-1)

grid = []
for h in range(H):
    grid.append(input().rstrip())

g = Grid(H, W, grid, (road, wall))

print(g.diameter2())

Submission status: Accepted

Solution code:
import queue
h,w=map(int,input().split())
s=[input() for _ in range(h)]
INF=10**18
dx=[-1,0,1,0]
dy=[0,-1,0,1]
ans=0
for i in range(h):
  for j in range(w):
    if s[i][j]=='#':continue
    d=[[INF]*w for _ in range(h)]
    d[i][j]=0
    q=queue.Queue()
    q.put((i,j))
    while not q.empty():
      x,y=q.get()
      for k in range(4):
        nx=x+dx[k]
        ny=y+dy[k]
        if 0<=nx<h and 0<=ny<w:
          if s[nx][ny]=='.' and d[nx][ny]==INF:
            q.put((nx,ny))
            d[nx][ny]=d[x][y]+1
            ans=max(ans,d[nx][ny])
print(ans)

Submission status: Accepted

Solution code:
#####################################################################################################
##### 幅優先探索　（初心者用グリッド、実行時間1.2倍）
#####################################################################################################

'''''''''''''''''''''
grid[h][w]

    w=0 w=1 w=2
h=0
h=1
h=2
'''''''''''''''''''''


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

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

    def connection_counter(self):
        """
        :return: 連結成分の個数。有効グラフではあまり意味がない。
        """
        cnt = 0
        self.parent = [[(-1,-1)] * self.W for _ in range(self.H)]
        for h in range(self.H):
            for w in range(self.W):
                if self.parent[h][w] == (-1, -1):
                    cnt += 1
                    self.bfs(start=(h,w), save=True)
        return cnt

    def distance_list(self, start=(0,0), save=False):
        """
        :param start: スタート地点
        :return: スタート地点から各点への距離のリスト
        """
        dist = [[-1] * self.W for _ in range(self.H)]
        if save:
            parent = self.parent
        else:
            parent = [[(-1, -1)] * self.W for _ in range(self.H)]
        p, t = start, 0
        parent[p[0]][p[1]] = (-2, -2)
        dist[p[0]][p[1]] = 0
        next_set = deque([(p, t)])

        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 self.grid[q[0]][q[1]] == self.wall:         # 壁があったら進まない
                    continue
                if parent[q[0]][q[1]] != (-1, -1):
                    continue
                dist[q[0]][q[1]] = t + 1
                parent[q[0]][q[1]] = p
                next_set.append((q, t + 1))
        return dist

    def most_distant_point(self, start=(0, 0), save=False):
        """
        :param start:
        :return: start 地点から最も遠い点を ((h,w), 距離) として出力
        """
        res = (start, 0)
        temp = 0
        dist = self.distance_list(start, save=save)
        for h in range(self.H):
            for w in range(self.W):
                if dist[h][w] > temp:
                    temp = dist[h][w]
                    res = ((h, w), temp)
        return res

    def diameter(self, start=(0,0), save=False):
        """
        :return:　木の直系（最も離れた二頂点間の距離）を返す
        """
        p = self.most_distant_point(start, save=False)
        res = self.most_distant_point(start=p[0], save=save)
        return res[1]

    def diameter2(self):
        """
        :return:　連結ではない時に、最大の直系を返す
        """
        res = 0
        for h in range(self.H):
            for w in range(self.W):
                if self.grid[h][w] == self.road and self.parent[h][w] == (-1, -1):
                    temp = self.diameter(start=(h, w), save=False)
                    if temp > res:
                        res = temp
        return res

    def dfs(self, start=(0, 0), goal=(-1, -1), time=0, save=False):
        """
        :param start: スタート地点
        :param goal: ゴール地点
        :param save: True = 前回の探索結果を保持する
        :return: ゴール地点までの距離。存在しなければ -1。ループがある時は最短距離とは限らないため注意。
        """

        if not save:
            self.parent = [[(-1, -1)] * self.W for _ in range(self.H)]
        move2 = [[marshal.loads(marshal.dumps(self.move)) for _ in range(self.W)] for _ in range(self.H)]

        p, t = start, time
        self.parent[p[0]][p[1]] = (-2, -2)
        while True:
            if move2[p]:
                dh, dw = move2[p].pop()
                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 self.grid[q[0]][q[1]] == self.wall:         # 壁があったら進まない
                    continue
                if q == self.parent[p[0]][p[1]]:
                    """ 逆流した時の処理 """
                    """"""""""""""""""""
                    continue
                if self.parent[q[0]][q[1]] != (-1, -1):
                    """ サイクルで同一点を訪れた時の処理 """
                    """"""""""""""""""""
                    continue
                #### (debug code) ######
                # debug(start, goal, q, t)
                ########################
                if q == goal:
                    """ ゴール時の処理"""
                    return t + 1
                    """"""""""""""""""""
                """ p から q への引継ぎ"""
                """"""""""""""""""""
                self.parent[q[0]][q[1]] = p
                p, t = q, t + 1
            else:
                """ p から進める点がもう無い時の点 p における処理 """
                """"""""""""""""""""
                if p == start and t == time:
                    break
                p, t = self.parent[p[0]][p[1]], t-1
                """ 点 p から親ノードに戻ってきた時の親ノードにおける処理 """
                """"""""""""""""""""
        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 != (None, None):
            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
import marshal
input = sys.stdin.readline



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

H, W = map(int,input().split())                # 左上は(h,w)=(0,0)、右下は(h,w)=(H-1,W-1)

grid = []
for h in range(H):
    grid.append(input().rstrip())

g = Grid(H, W, grid, road_wall, destroy=False)

print(g.diameter2())

Submission status: Accepted

Solution code:
import queue
h,w=map(int,input().split())
s=[input() for _ in range(h)]
INF=10**18
dx=[-1,0,1,0]
dy=[0,-1,0,1]
ans=0
for i in range(h):
  for j in range(w):
    if s[i][j]=='#':continue
    d=[[INF]*w for _ in range(h)]
    d[i][j]=0
    q=queue.Queue()
    q.put((i,j))
    while not q.empty():
      x,y=q.get()
      for k in range(4):
        nx=x+dx[k]
        ny=y+dy[k]
        if 0<=nx<h and 0<=ny<w:
          if s[nx][ny]=='.' and d[nx][ny]==INF:
            q.put((nx,ny))
            d[nx][ny]=d[x][y]+1
            ans=max(ans,d[nx][ny])
print(ans)

Submission status: Accepted

Solution code:
h,w=map(int,input().split())
g=[input() for _ in range(h)]
from collections import *
def bfs(x,y):
  d=[[-1]*w for _ in range(h)]
  d[x][y]=0
  q=deque([(x,y)])
  while q:
    tx,ty=q.popleft()
    for dx,dy in [(1,0),(0,1),(-1,0),(0,-1)]:
      nx,ny=tx+dx,ty+dy
      if 0<=nx<h and 0<=ny<w and g[nx][ny]=='.' and d[nx][ny]<0:
        r=d[nx][ny]=d[tx][ty]+1
        q.append((nx,ny))
  return r
print(max(bfs(x,y) for x in range(h) for y in range(w) if g[x][y]=='.'))

Submission status: Accepted

Solution code:
# D - Maze Master
# https://atcoder.jp/contests/abc151/tasks/abc151_d
from collections import deque


def main():
    height, width = [int(num) for num in input().split()]
    maze = [input() for _ in range(height)]

    ans = 0
    next_to = ((0, 1), (1, 0), (0, -1), (-1, 0))

    for start_x in range(height):
        for start_y in range(width):
            if maze[start_x][start_y] == '#':
                continue
            queue = deque()
            queue.append((start_x, start_y))
            reached = [[-1] * width for _ in range(height)]
            reached[start_x][start_y] = 0

            while queue:
                now_x, now_y = queue.popleft()
                for move_x, move_y in next_to:
                    adj_x, adj_y = now_x + move_x, now_y + move_y
                    # Python は index = -1 が通ってしまうことに注意。
                    # except IndexError では回避できない。
                    if (not 0 <= adj_x < height
                            or not 0 <= adj_y < width
                            or maze[adj_x][adj_y] == '#'
                            or reached[adj_x][adj_y] != -1):
                        continue
                    queue.append((adj_x, adj_y))
                    reached[adj_x][adj_y] = reached[now_x][now_y] + 1
            most_distant = max(max(row) for row in reached)
            ans = max(most_distant, ans)
    print(ans)


if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
'''''''''''''''''''''
grid[h][w]

    w=0 w=1 w=2
h=0
h=1
h=2
'''''''''''''''''''''

from collections import deque
import sys
sys.setrecursionlimit(10 ** 8)
input = sys.stdin.readline
move = [(1, 0), (-1, 0), (0, 1), (0, -1)]     # 動ける場所の候補


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


def distance_list(grid, visit, start, goal=(None,None)):
    dist = [[-1] * W for _ in range(H)]
    dist[start[0]][start[1]] = 0
    visit[start[0]][start[1]] = 1
    next_set = deque([(start, 0)])
    while next_set:
        p, t = next_set.popleft()
        h, w = p
        for dh, dw in move:
            q = (h + dh, w + dw)
            if q[0] < 0 or q[0] >= H or q[1] < 0 or q[1] >= W:
                continue
            if grid[q[0]][q[1]] == wall:
                continue
            if visit[q[0]][q[1]] == 1:
                continue
            #### (debug code) ######
            # debug(start, goal, q, t)
            ########################
            if q == goal:
                return t + 1
            visit[q[0]][q[1]] = 1
            dist[q[0]][q[1]] = t+1
            next_set.append((q, t + 1))
    return dist


def most_distant_point(grid, visit, start=(0,0)):
    res = (start, 0)
    temp = 0
    dist = distance_list(grid, visit, start)
    for h in range(H):
        for w in range(W):
            if dist[h][w] > temp:
                temp = dist[h][w]
                res = ((h,w), temp)
    return res


def diameter(grid, visit, start=(0,0)):
    visit = [[0] * W for _ in range(H)]
    p = most_distant_point(grid, visit, start)
    visit = [[0]*W for _ in range(H)]
    res = most_distant_point(grid, visit, start=p[0])
    return res[1]


def diameter2(grid):
    res = 0
    for h in range(H):
        for w in range(W):
            if grid[h][w] == road and visit[h][w] == 0:
                temp = diameter(grid, visit, (h,w))
                if temp > res:
                    res =temp
    return res

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


######################################################
# スタート地点がinputで与えられる場合 (h軸とw軸の反転に注意)
######################################################

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

H,W = map(int,input().split())                # 左上は(h,w)=(0,0)、右下は(h,w)=(H-1,W-1)

grid = []
for h in range(H):
    grid.append(input().rstrip())                # 文字列を読み込むと改行が入るため、rstrip()で消す

visit = [[0]*W for _ in range(H)]
res = diameter2(grid)           #  visitを初期化せずに何度も呼び出すと、visit が変わって返り値も変わるので注意

print(res)

Submission status: Accepted

Solution code:
h,w=map(int,input().split())
g=[input() for _ in range(h)]
from collections import *
def bfs(sx,sy):
  d=[[-1]*w for _ in range(h)]
  d[sx][sy]=0
  q=deque([(sx,sy)])
  while q:
    x,y=q.popleft()
    for dx,dy in [(1,0),(0,1),(-1,0),(0,-1)]:
      nx,ny=x+dx,y+dy
      if 0<=nx<h and 0<=ny<w and g[nx][ny]=='.' and d[nx][ny]<0:
        r=d[nx][ny]=d[x][y]+1
        q.append((nx,ny))
  return r
print(max(bfs(x,y) for x in range(h) for y in range(w) if g[x][y]=='.'))

Submission status: Accepted

Solution code:
h,w=map(int,input().split())
g=[input() for _ in range(h)]
from collections import *
def bfs(sx,sy):
  d=[[-1]*w for _ in range(h)]
  d[sx][sy]=0
  q=deque([(sx,sy)])
  while q:
    x,y=q.popleft()
    for dx,dy in [(1,0),(0,1),(-1,0),(0,-1)]:
      nx,ny=x+dx,y+dy
      if 0<=nx<h and 0<=ny<w and g[nx][ny]=='.' and d[nx][ny]<0:
        r=d[nx][ny]=d[x][y]+1
        q.append((nx,ny))
  return r
print(max(bfs(sx,sy) for sx in range(h) for sy in range(w) if g[sx][sy]=='.'))

Submission status: Accepted

Solution code:
h,w=map(int,input().split())
g=[[*input()] for _ in range(h)]
from collections import *
def bfs(sx,sy):
  d=[[-1]*w for _ in range(h)]
  d[sx][sy]=0
  q=deque([(sx,sy)])
  while q:
    x,y=q.popleft()
    t=d[x][y]+1
    for dx,dy in [(1,0),(0,1),(-1,0),(0,-1)]:
      nx,ny=x+dx,y+dy
      if 0<=nx<h and 0<=ny<w and g[nx][ny]=='.' and d[nx][ny]<0:
        d[nx][ny]=t
        q.append((nx,ny))
  return d
import numpy as np
a=0
for sx in range(h):
  for sy in range(w):
    if g[sx][sy]=='#': continue
    a=max(a,np.max(bfs(sx,sy)))
print(a)

Submission status: Accepted

Solution code:
h,w=map(int,input().split())
g=[[*input()] for _ in range(h)]
from collections import *
a=0
for sx in range(h):
  for sy in range(w):
    if g[sx][sy]=='#': continue
    d=[[-1]*w for _ in range(h)]
    d[sx][sy]=0
    q=deque([(sx,sy)])
    while q:
      x,y=q.popleft()
      t=d[x][y]+1
      for dx,dy in [(1,0),(0,1),(-1,0),(0,-1)]:
        nx,ny=x+dx,y+dy
        if 0<=nx<h and 0<=ny<w and g[nx][ny]=='.' and d[nx][ny]<0:
          d[nx][ny]=t
          q.append((nx,ny))
          a=max(a,t)
print(a)

Submission status: Accepted

Solution code:
h,w=map(int,input().split())
g=[input() for _ in range(h)]
import numpy as np
from collections import *
a=0
for sx in range(h):
  for sy in range(w):
    if g[sx][sy]=='#': continue
    d=[[-1]*w for _ in range(h)]
    d[sx][sy]=0
    q=deque([(sx,sy)])
    while q:
      x,y=q.popleft()
      for dx,dy in [(1,0),(0,1),(-1,0),(0,-1)]:
        nx,ny=x+dx,y+dy
        if 0<=nx<h and 0<=ny<w and g[nx][ny]=='.' and d[nx][ny]<0:
          d[nx][ny]=d[x][y]+1
          q.append((nx,ny))
    a=max(a,np.max(d))
print(a)

Submission status: Accepted

Solution code:
h,w=map(int,input().split())
g=[[*input()] for _ in range(h)]
from collections import *
a=0
for sx in range(h):
  for sy in range(w):
    if g[sx][sy]=='#': continue
    d=[[-1]*w for _ in range(h)]
    d[sx][sy]=0
    q=deque([(sx,sy)])
    while q:
      x,y=q.popleft()
      for dx,dy in [(1,0),(0,1),(-1,0),(0,-1)]:
        nx,ny=x+dx,y+dy
        if 0<=nx<h and 0<=ny<w and g[nx][ny]=='.' and d[nx][ny]<0:
          d[nx][ny]=d[x][y]+1
          q.append((nx,ny))
    a=max(a,max(max(i for i in l) for l in d))
print(a)

Submission status: Accepted

Solution code:
from queue import Queue
import copy

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

f = [["#"] * (w + 2)] + \
    [list("#" + input() + "#") for i in range(h)] + \
    [["#"] * (w + 2)]
dxy = [(0,1), (0,-1), (1,0), (-1,0)]

d = [[-1]*(w+2) for i in range(h+2)]
for iy in range(h+2):
    for ix in range(w+2):
        if f[iy][ix] == '#':
            d[iy][ix] = 1000

ans = 0
for sy in range(h+2):
    for sx in range(w+2):
        if f[sy][sx] == '#':
            continue
        dist = copy.deepcopy(d)
        cnt = 0
        cnt_max = 0
        q = Queue()
        q.put([sy, sx])
        dist[sy][sx] = 0
        while q.qsize():
            y, x = q.get()
            cnt = dist[y][x]
            
            # print(sx, sy, x, y)
            cnt_max = max(cnt_max, cnt)
            for dy, dx in dxy:
                ny, nx = y + dy, x + dx
                if dist[ny][nx] == 1000:
                    continue
                if dist[ny][nx] == -1:
                    q.put([ny, nx])
                    dist[ny][nx] = cnt + 1
        # print(sx, sy, x, y, cnt)
        ans = max(ans, cnt_max)
print(ans)

Submission status: Accepted

Solution code:
h,w = map(int,input().split())
L = [[]*w for i in range(h)]

for i in range(h):
    L[i] = list("#" + input() + "#")
L = [["#" for i in range(w+2)]] + L + [["#" for i in range(w+2)]]
#print(L)

from collections import deque
ans = 0
q = deque([])
for j in range(1,h+1):
    for i in range(1,w+1):
        cost = [[-1]*(w+2) for i in range(h+2)]
        li = ((1,0),(0,1),(-1,0),(0,-1))
        #print(j,i)
        if L[j][i] == ".":
            cost[j][i] = 0
        cost_max = 0
        q.append((j,i))
        while q:
            #print(q)
            r,s = q.popleft()
            
            for dh,dw in li:
                nh,nw = r+dh,s+dw
                #print(L[nh][nw],)
                if L[nh][nw] =="." and cost[nh][nw] == -1 :
                    cost[nh][nw] = cost[r][s] + 1
                    #print(cost[nh][nw],cost[j][i])
                    #print(cost)
                    cost_max = max(cost_max,cost[nh][nw])
                    q.append((nh,nw))
        ans = max(ans,cost_max)
print(ans)

Submission status: Accepted

Solution code:
from collections import deque

def getMaxDistance(s,startY,startX):
  d = deque()
  distances = [[0 for _ in range(w)] for j in range(h)]
  dx = [-1, 0, 1, 0]
  dy = [0, 1, 0, -1]
  maxDistance = 0
  d.append(startX)
  d.append(startY)
  while d:
    x = d.popleft()
    y = d.popleft()
    if s[y][x]=='#': continue
    maxDistance = max(maxDistance, distances[y][x])
    for i in range(4):
      xx = x + dx[i]
      yy = y + dy[i]
      if not (0 <= yy < h and 0 <= xx < w): continue
      if s[yy][xx] != '.': continue
      if distances[yy][xx] != 0: continue
      if xx == startX and yy == startY: continue
      d.append(xx)
      d.append(yy)
      distances[yy][xx] = distances[y][x] + 1
  return maxDistance

h,w=map(int,input().split())
s=[list(input()) for _ in range(h)]
maxDistance = 0
for i in range(h):
  for j in range(w):
    maxDistance = max(maxDistance, getMaxDistance(s,i,j))
print(maxDistance)