각 대기실에 있는 응시자가 거리두기를 잘 지키고 있는 지 알아보는 문제.
응시자간 사이의 거리를 맨해튼 거리로 정의하고 맨해튼 거리가 2이하이면 거리두기를 못 지켰다고 할 수 있다. 단, 맨해튼 거리가 2이하이더라도, 중간에 파티션이 존재하면 거리두기를 잘 지킨 것이다.
맨해튼 거리의 정의는
|y1-y2|+|x1-x2|
이다.(맨해튼거리-위키백과 참고)
문제를 이해했다면, 아래와 같이 해석할 수 있다.
어떤 대기실에 있는 사람A가 있는 칸에서 출발하여, 인접한 칸에 대해 상하좌우로 움직이면서, 사람B가 있는 칸까지간다. 파티션이 있는 칸은 갈 수 없을 때, 사람B까지 도달하는 최단 거리를 구한다. 최단 거리가 2이하이면 거리두기를 지켰다고 할 수 없다.
따라서 각 사람들을 출발점으로 지정하고 BFS를 이용하여 다른 사람들까지의 맨해튼 거리를 구하고 거리두기를 지켰는지 확인하다.
필력이 좋은편은 아니라서, 더 깔끔한 해설은 2021 카카오 인턴십 코딩테스트 해설을 참고하길 바란다.
from collections import deque
d = ((0,1), (1,0), (-1,0), (0,-1))
SIZE = 5
def make_maps(place):
arr = []
men = []
for i, string in enumerate(place):
for j, ch in enumerate(string):
if ch == 'P':men.append((i,j))
arr.append(list(string))
return arr, men
def isin(y,x):
if -1<y<SIZE and -1<x<SIZE: return True
return False
def bfs(arr, sy, sx):
q = deque()
q.append((sy, sx))
table = [[-1 for _ in range(SIZE)] for _ in range(SIZE)]
table[sy][sx] = 0
while q:
y, x = q.popleft()
for dy, dx in d:
ny = y + dy
nx = x + dx
if not isin(ny, nx): continue
if arr[ny][nx] != 'X' and table[ny][nx] == -1:
table[ny][nx] = table[y][x] + 1
q.append((ny, nx))
return table
def solution(places):
answer = []
for place in places:
arr, men = make_maps(place)
ok = True
for man in men:
table = bfs(arr, man[0], man[1])
for other_man in men:
if man != other_man:
y = other_man[0]
x = other_man[1]
if -1 < table[y][x] <= 2:
ok = False
break
if not ok: break
if ok: answer.append(1)
else: answer.append(0)
return answer