[programmers] 거리두기 확인하기

wonyu·2022년 2월 19일
0

algorithm

목록 보기
23/25

문제 링크

https://programmers.co.kr/learn/courses/30/lessons/81302

풀이 방법


우선 5개의 대기실 정보가 주어지므로 각 대기실 정보에 대해 distance_check() 함수를 실행한다. 대기실에 사람(=P)이 한 명도 없는 경우를 처리하기 위한 코드가 필요하고, 모든 자리에 대해 거리두기 여부를 확인해야 한다.

만약에 해당 자리에 사람이 있을 경우에 대해서만 주변 자리를 체크하는데, 처음에는 위 그림에서 주황색으로 표시된 8자리만 확인하면 될 거라고 생각했다. 하지만 맨해튼 거리가 2 이하인 자리를 모두 확인하려면 파란색 자리(상하좌우에 대해 2칸 떨어진 자리)도 확인해야 했다.

그리고 상하좌우 자리에 바로 P가 있다면 P와 P가 맞닿아 있으므로 바로 0을 리턴하면 되지만, 대각선이거나 2칸 떨어진 경우에는 어떻게 체크하면 좋을지 고민이었다. 그러다가 문득 이중 for문을 이용해서 두 칸 중 앞쪽 칸부터 뒤쪽 칸까지의 범위 내에 파티션이 없다면(=값이 O라면) 리턴하면 되겠다는 생각이 들어서 이 방식으로 구현했다.

코드

delta = [[-1, -1], [-1, 0], [-2, 0], [-1, 1], [0, 1], [0, 2], [1, 1], [1, 0], [2, 0], [1, -1], [0, -1], [0, -2]]

# 맨해튼 거리가 2가 되는 상하좌우로 2칸 떨어진 곳도 확인해야 함 -> tc 2개 틀린 이유


def check_place(x, y):
    if 0 <= x < 5 and 0 <= y < 5:
        return True
    return False


def distance_check(p):
    val = 1
    for r in range(5):
        # row에 사람이 없으면 다음 줄 확인
        if 'P' not in p[r]:
            continue
        for c in range(5):
            # 사람이 있을 경우 -> 주위 자리 체크
            if p[r][c] == 'P':
                for i in range(12):
                    nr = r + delta[i][0]
                    nc = c + delta[i][1]
                    # 주위 자리에 사람이 있다면
                    if check_place(nr, nc) and p[nr][nc] == 'P':
                        # 상하좌우 자리면 바로 0 리턴
                        if (delta[i][0] == 0 or delta[i][1] == 0) and 2 not in delta[i] and -2 not in delta[i]:
                            return 0
                        else:
                            # 그 주위에 파티션이 없으면 0 리턴
                            for i in range(min(r, nr), max(r, nr) + 1):
                                for j in range(min(c, nc), max(c, nc) + 1):
                                    if p[i][j] == 'O':
                                        return 0
    return 1


def solution(places):
    answer = []

    for place in places:
        answer.append(distance_check(place))
    return answer

0개의 댓글