일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 멀티모듈
- EC2
- multi module
- DP
- 탄력적 ip
- C++
- localdatetime
- 자료구조
- DIP
- OCP
- 구현
- aws
- 해시충돌
- SW마에스트로
- 비즈니스요구사항
- google calendar api
- DFS
- 완전탐색
- BFS
- ZonedDateTime
- 정렬
- 그리디
- 서버
- hashcollision
- 서버타임존설정
- web
- STL
- 개방주소법
- 에러로깅
- 객체지향설계
- Today
- Total
레츠고✨
[프로그래머스] 아이템 줍기 (python) 본문
문제 설명
다음과 같은 다각형 모양 지형에서 캐릭터가 아이템을 줍기 위해 이동하려 합니다.
지형은 각 변이 x축, y축과 평행한 직사각형이 겹쳐진 형태로 표현하며, 캐릭터는 이 다각형의 둘레(굵은 선)를 따라서 이동합니다.
만약 직사각형을 겹친 후 다음과 같이 중앙에 빈 공간이 생기는 경우, 다각형의 가장 바깥쪽 테두리가 캐릭터의 이동 경로가 됩니다.
단, 서로 다른 두 직사각형의 x축 좌표 또는 y축 좌표가 같은 경우는 없습니다.
즉, 위 그림처럼 서로 다른 두 직사각형이 꼭짓점에서 만나거나, 변이 겹치는 경우 등은 없습니다.
다음 그림과 같이 지형이 2개 이상으로 분리된 경우도 없습니다.
한 직사각형이 다른 직사각형 안에 완전히 포함되는 경우 또한 없습니다.
지형을 나타내는 직사각형이 담긴 2차원 배열 rectangle, 초기 캐릭터의 위치 characterX, characterY, 아이템의 위치 itemX, itemY가 solution 함수의 매개변수로 주어질 때, 캐릭터가 아이템을 줍기 위해 이동해야 하는 가장 짧은 거리를 return 하도록 solution 함수를 완성해주세요.
제한 사항
- rectangle의 세로(행) 길이는 1 이상 4 이하입니다.
- rectangle의 원소는 각 직사각형의 [좌측 하단 x, 좌측 하단 y, 우측 상단 x, 우측 상단 y] 좌표 형태입니다.
- 직사각형을 나타내는 모든 좌표값은 1 이상 50 이하인 자연수입니다.
- 서로 다른 두 직사각형의 x축 좌표, 혹은 y축 좌표가 같은 경우는 없습니다.
- 문제에 주어진 조건에 맞는 직사각형만 입력으로 주어집니다.
- charcterX, charcterY는 1 이상 50 이하인 자연수입니다.
- 지형을 나타내는 다각형 테두리 위의 한 점이 주어집니다.
- itemX, itemY는 1 이상 50 이하인 자연수입니다.
- 지형을 나타내는 다각형 테두리 위의 한 점이 주어집니다.
- 캐릭터와 아이템의 처음 위치가 같은 경우는 없습니다.
입출력 예
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 |
풀이
1. 2배 큰 보드판 배열을 생성한다.
2. 각 직사각형을 2배로 그린다.
3. 캐릭터 시작지점과 아이템 위치를 2배 늘린 좌표로부터 시작하여, BFS를 통해 보드판 경계선을 따라 이동시킨다.
4. visited 2차원 배열에 해당 좌표까지 이동한 거리를 저장한다.
5. 캐릭터가 아이템과 만나면 해당 좌표의 거리를 2로 나누어 출력한다.
이 문제에서는 ⭐좌표를 2배로 늘리는 것이 핵심 아이디어였다.
예를 들면, 위처럼 (7, 5)위치에서 다음 좌표로 이동할 때,
왼쪽으로 한 칸 이동하는 (6, 5)와
아래로 한 칸 이동하는 (7, 4) 모두 테두리에 속하는 좌표이다.
하지만 (6, 5)는 내부에 위치한 테두리이기 때문에 왼쪽으로 간다면 좌표가 잘못된 방향으로 이동하게 된다.
이런 경우를 방지하기 위해서 절반만 이동하여 해당 좌표로 이동하는 방향이 올바른지 판단하는 과정이 필요한데,
2차원 리스트에서 0.5만큼만 이동할 수는 없기 때문에 아예 2배로 확장하여 같은 효과를 내는 것이다.
from collections import deque
def solution(rectangle, characterX, characterY, itemX, itemY):
answer = 0
cx, cy = 2*characterX, 2*characterY
ix, iy = 2*itemX, 2*itemY
board = [[-1]*102 for _ in range(102)]
visited = [[1] * 102 for _ in range(102)]
# draw
for r in rectangle:
a, b, c, d = map(lambda x: x*2, r)
for x in range(a, c+1):
for y in range(b, d+1):
if a < x < c and b < y < d:
board[x][y] = 0
elif board[x][y] != 0:
board[x][y] = 1
dx = [0, 1, 0, -1]
dy = [1, 0, -1, 0]
# bfs
q = deque()
q.append((cx, cy))
visited[cx][cy] = 0
while q:
x, y = q.popleft()
if x == ix and y == iy:
answer = visited[x][y] // 2
break
for i in range(4):
nx = x+ dx[i]
ny = y+ dy[i]
if nx < 0 or nx > 102 or ny < 0 or ny > 102:
continue
if board[nx][ny] == 1:
if visited[nx][ny] == 1:
visited[nx][ny] = visited[x][y] + 1
q.append((nx, ny))
return answer
알고리즘 유형
- BFS
'Problem Solving > Solution' 카테고리의 다른 글
[백준] 보석 도둑 (python) (0) | 2024.04.01 |
---|---|
[프로그래머스] 큰 수 만들기 (python) (0) | 2024.02.28 |
[프로그래머스] 조이스틱 (python) (3) | 2024.02.27 |
[프로그래머스] 전력망을 둘로 나누기 (python) (0) | 2024.02.16 |
[백준] 1182. 부분 수열의 합 (python) (1) | 2024.02.15 |