Lv5. 방의 개수 ( Python )
# 문제 설명
원점(0,0)에서 시작해서 아래처럼 숫자가 적힌 방향으로 이동하며 선을 긋습니다.
ex) 1일때는 오른쪽 위
로 이동
그림을 그릴 때, 사방이 막히면 방하나로 샙니다. 이동하는 방향이 담긴 배열 arrows가 매개변수로 주어질 때, 방의 갯수를 return 하도록 solution 함수를 작성하세요.
# 제한 사항
- 배열 arrows의 크기는 1 이상 100,000 이하 입니다.
- arrows의 원소는 0 이상 7 이하 입니다.
- 방은 다른 방으로 둘러 싸여질 수 있습니다.
# 입출력 예
arrows | return |
---|---|
[6, 6, 6, 4, 4, 4, 2, 2, 2, 0, 0, 0, 1, 6, 5, 5, 3, 6, 0] | 3 |
입출력 예 설명
- (0,0) 부터 시작해서 6(왼쪽) 으로 3번 이동합니다. 그 이후 주어진 arrows 를 따라 그립니다.
- 삼각형 (1), 큰 사각형(1), 평행사변형(1) = 3
문제 해결 시 고려사항
- 지나갔던 경로에 대한 처리(방향 정보 저장)
본 문제는 원점으로 시작하여 주어지는 방향 정보에 따른 이동으로 발생하는 선분들로 인해 생기는 공간의 개수를 카운트하는 문제이다. 단순히 생각하면 선분 간의 교차점을 통해 공간 생성 유무를 판단할 수 있지만, 지났던 방향을 다시 지나게 된다면 그 또한 교차로 판단되어 카운트 될 것이다.
따라서, 본 문제는 이동 간의 이동 방향에 대한 정보를 계속해서 저장하며 탐색해야 하는 문제인 것이다. 문제의 풀이 과정은 아래와 같다.
arrows 방향에 대해 방향정보,방문여부를 딕셔너리 및 큐에 저장
chck, direc, q = {}, {}, deque() chck[(0, 0)] = 0 q.append([0, 0]) x, y, ans = 0, 0, 0 # arrows 방향에 대해 방향정보,방문여부를 딕셔너리 및 큐에 저장 for i in arrows: for j in range(2): currx = x + dx[i] curry = y + dy[i] chck[(currx, curry)] = 0 direc[(x, y, currx, curry)] = 0 direc[(currx, curry, x, y)] = 0 q.append([currx, curry]) x, y = currx, curry x, y = q.popleft() chck[(x, y)] = 1
현재 위치와 다음 위치에 대한 검사 실시
while q: # 현재 위치와 다음 위치에 대한 검사 실시 nx, ny = q.popleft() # 이동할 위치가 방문한 적이 있고 if chck[(nx, ny)] == 1: # 전에 이동을 했던 방향이 아니라면 if direc[(x, y, nx, ny)] == 0: # 답 증가, 해당 구간 이동여부 변경 ans += 1 direc[(x, y, nx, ny)] = 1 direc[(nx, ny, x, y)] = 1 # 이동할 위치에 방문한적이 없다면 else: # 해당 위치 방문 여부 변경 및 해당 구간 이동여부 변경 chck[(nx, ny)] = 1 direc[(x, y, nx, ny)] = 1 direc[(nx, ny, x, y)] = 1 # 현재 위치를 이동할 위치였던 좌표로 변경 x, y = nx, ny
위의 반복을 통해 카운트 한 정답 반환
return ans
전체 코드
from collections import deque
# 방향 정보 리스트
dx = [-1, -1, 0, 1, 1, 1, 0, -1]
dy = [0, 1, 1, 1, 0, -1, -1, -1]
def solution(arrows):
chck, direc, q = {}, {}, deque()
chck[(0, 0)] = 0
q.append([0, 0])
x, y, ans = 0, 0, 0
# arrows 방향에 대해 방향정보,방문여부를 딕셔너리 및 큐에 저장
for i in arrows:
for j in range(2):
currx = x + dx[i]
curry = y + dy[i]
chck[(currx, curry)] = 0
direc[(x, y, currx, curry)] = 0
direc[(currx, curry, x, y)] = 0
q.append([currx, curry])
x, y = currx, curry
x, y = q.popleft()
chck[(x, y)] = 1
while q:
# 현재 위치와 다음 위치에 대한 검사 실시
nx, ny = q.popleft()
# 이동할 위치가 방문한 적이 있고
if chck[(nx, ny)] == 1:
# 전에 이동을 했던 방향이 아니라면
if direc[(x, y, nx, ny)] == 0:
# 답 증가, 해당 구간 이동여부 변경
ans += 1
direc[(x, y, nx, ny)] = 1
direc[(nx, ny, x, y)] = 1
# 이동할 위치에 방문한적이 없다면
else:
# 해당 위치 방문 여부 변경 및 해당 구간 이동여부 변경
chck[(nx, ny)] = 1
direc[(x, y, nx, ny)] = 1
direc[(nx, ny, x, y)] = 1
# 현재 위치를 이동할 위치였던 좌표로 변경
x, y = nx, ny
return ans