다음과 같은 다각형 모양 지형에서 캐릭터가 아이템을 줍기 위해 이동하려 합니다.
지형은 각 변이 x축, y축과 평행한 직사각형이 겹쳐진 형태로 표현하며, 캐릭터는 이 다각형의 둘레(굵은 선)를 따라서 이동합니다.
만약 직사각형을 겹친 후 다음과 같이 중앙에 빈 공간이 생기는 경우, 다각형의 가장 바깥쪽 테두리가 캐릭터의 이동 경로가 됩니다.
단, 서로 다른 두 직사각형의 x축 좌표 또는 y축 좌표가 같은 경우는 없습니다.
즉, 위 그림처럼 서로 다른 두 직사각형이 꼭짓점에서 만나거나, 변이 겹치는 경우 등은 없습니다.
다음 그림과 같이 지형이 2개 이상으로 분리된 경우도 없습니다.
한 직사각형이 다른 직사각형 안에 완전히 포함되는 경우 또한 없습니다.
지형을 나타내는 직사각형이 담긴 2차원 배열 rectangle, 초기 캐릭터의 위치 characterX, characterY, 아이템의 위치 itemX, itemY가 solution 함수의 매개변수로 주어질 때, 캐릭터가 아이템을 줍기 위해 이동해야 하는 가장 짧은 거리를 return 하도록 solution 함수를 완성해주세요.
rectangle characterX characterY itemX itemY result
[[1,1,7,4],[3,2,5,5],[4,3,6,9],[2,6,8,8]] 1 3 7 8 17
[[1,1,8,4],[2,2,4,9],[3,6,9,8],[6,3,7,7]] 9 7 6 1 11
[[1,1,5,7]] 1 1 4 7 9
[[2,1,7,5],[6,4,10,10]] 3 1 7 10 15
[[2,2,5,5],[1,3,6,4],[3,1,4,6]] 1 4 6 3 10
Code
from collections import deque def solution(rectangle, characterX, characterY, itemX, itemY): answer = 0 maps = [[-1]*102 for _ in range(102)] # 이동할 수 있는 경로 for r in rectangle: x1, y1, x2, y2 = map(lambda x: x*2, r) for i in range(x1, x2+1): for j in range(y1, y2+1): if x1 < i < x2 and y1 < j < y2: # 내부인 경우 maps[i][j] = 0 elif maps[i][j] != 0: # 테두리인 경우 maps[i][j] = 1 dx = [-1,1,0,0] dy = [0,0,-1,1] visited = [[1]*102 for _ in range(102)] # 방문 여부 q = deque() q.append((characterX*2, characterY*2)) while q: x, y = q.popleft() if x == itemX*2 and y == itemY*2: # 아이템과 캐릭터의 위치가 같은 경우 answer = visited[x][y] // 2 break for v in range(4): nx = x + dx[v] ny = y + dy[v] if maps[nx][ny] == 1 and visited[nx][ny] == 1: q.append((nx, ny)) visited[nx][ny] = visited[x][y] + 1 # 거리 누적 return answer
- 최단거리를 찾는 문제이므로 bfs 알고리즘을 활용함
- 2차원 리스트(maps)를 생성하여 테두리는 1, 내부는 0, 외부는 -1로 채워 지도를 만듦
- 방문 여부를 확인하는 visited와 maps를 바탕으로 bfs로 최단거리를 찾음
- 이때 이차원 리스트로 bfs를 진행하는 경우 테두리가 인접해있으면 경로를 잘못 찾는 문제가 있으므로 좌표를 그릴 때 2배로 생성하여 구현하였음