https://school.programmers.co.kr/learn/courses/30/lessons/87694
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
문제 설명
다음과 같은 다각형 모양 지형에서 캐릭터가 아이템을 줍기 위해 이동하려 합니다.

지형은 각 변이 x축, y축과 평행한 직사각형이 겹쳐진 형태로 표현하며, 캐릭터는 이 다각형의 둘레(굵은 선)를 따라서 이동합니다.
만약 직사각형을 겹친 후 다음과 같이 중앙에 빈 공간이 생기는 경우, 다각형의 가장 바깥쪽 테두리가 캐릭터의 이동 경로가 됩니다.

단, 서로 다른 두 직사각형의 x축 좌표 또는 y축 좌표가 같은 경우는 없습니다.

즉, 위 그림처럼 서로 다른 두 직사각형이 꼭짓점에서 만나거나, 변이 겹치는 경우 등은 없습니다.
다음 그림과 같이 지형이 2개 이상으로 분리된 경우도 없습니다.

한 직사각형이 다른 직사각형 안에 완전히 포함되는 경우 또한 없습니다.

지형을 나타내는 직사각형이 담긴 2차원 배열 rectangle, 초기 캐릭터의 위치 characterX, characterY, 아이템의 위치 itemX, itemY가 solution 함수의 매개변수로 주어질 때, 캐릭터가 아이템을 줍기 위해 이동해야 하는 가장 짧은 거리를 return 하도록 solution 함수를 완성해주세요.
이 문제의 제한 조건 중 rectangle의 세로(행) 길이는 1 이상 4 이하였고, 직사각형을 나타내는 모든 좌표값은 1 이상 50 이하인 자연수임이 있다. 문제 제한 조건을 보니 그렇게 시간 초과가 문제가 될만한 문제는 아니었다.
이동 가능한 좌표값들이 주어졌을 때 bfs를 진행하는 것 또한 어려운 일은 아니었지만, 문제는 이동 가능한 좌표값들을 표시해야하는 부분이었다.. 좌표값들이 문제처럼 자연수를 값으로 좌표를 만들면 컴퓨터 상에서 BFS 진행 시, 원래는 이동 불가능한 곳이 이동하게 되는 문제점이 발생한다.
이에 대한 해결책으로 좌표를 2배 확대하였고, 그에 따라 좌표값들만 조금 신경써주니 해결되었다!
<< 전체 코드 >>
from collections import deque
def pos_inRec(i, j, recs): # 좌표값이 직사각형 내부에 있는지 확인
for rec in recs:
if (rec[1]*2<i and i<rec[3]*2) and (rec[0]*2<j and j<rec[2]*2):
return True
return False
def make_board(recs): # 좌표 구하기
board = [[0 for j in range(102)] for i in range(102)]
for rec in recs:
for i in range(rec[1]*2, rec[3]*2+1):
board[i][rec[0]*2] = board[i][rec[2]*2] = 1
for j in range(rec[0]*2, rec[2]*2+1):
board[rec[1]*2][j] = board[rec[3]*2][j] = 1
for i in range(102):
for j in range(102):
if board[i][j] == 1 and pos_inRec(i, j, recs):
board[i][j] = 0
return board
def bfs(curX, curY, itemX, itemY, board): # 최단 경로 구하기
dy = [-1, 1, 0, 0]
dx = [0, 0, -1, 1]
q = deque()
q.append([curY*2, curX*2, 0])
board[curY*2][curX*2] = 0
while q:
y, x, distance = q.popleft()
if y == itemY*2 and x == itemX*2:
return distance
for i in range(4):
ny = y + dy[i]
nx = x + dx[i]
if ny < 0 or ny >= 102 or nx < 0 or nx >= 102:
continue
if board[ny][nx] == 1:
q.append([ny, nx, distance + 1])
board[ny][nx] = 0
def solution(recs, curX, curY, itemX, itemY):
board = make_board(recs) # 좌표 구하기
min_distance = bfs(curX, curY, itemX, itemY, board) # 최단 경로 구하기
return min_distance // 2
'코딩테스트 > 프로그래머스' 카테고리의 다른 글
[프로그래머스 Level2] 이모티콘 할인행사 - 파이썬(Python) - 2023 KAKAO BLIND RECRUITMENT (0) | 2023.01.05 |
---|---|
[프로그래머스 Level3] 모두 0으로 만들기 - 파이썬(Python) - 월간 코드 챌린지 시즌2 (0) | 2022.12.28 |
[프로그래머스 Level3] 풍선 터트리기 - 파이썬(Python) - 월간 코드 챌린지 시즌1 (0) | 2022.12.27 |
[프로그래머스 Level2] 숫자 카드 나누기 - 파이썬(Python) (0) | 2022.12.27 |
[프로그래머스 Level3] 섬 연결하기 - 파이썬(Python) (0) | 2022.12.13 |