문제
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 이하입니다.
- rectangle의 원소는 각 직사각형의 [좌측 하단 x, 좌측 하단 y, 우측 상단 x, 우측 상단 y] 좌표 형태입니다.
- charcterX, charcterY는 1 이상 50 이하인 자연수입니다.
- itemX, itemY는 1 이상 50 이하인 자연수입니다.
- 캐릭터와 아이템의 처음 위치가 같은 경우는 없습니다.
풀이
아이디어
최단 경로 문제가 나오면 자동으로 BFS가 떠오르도록 하면 좋다
카테고리에 나와있듯 너무나도 BFS문제 ㅎㅎ
처음 생각은 갈 수 있는 경로를 표시한 후 이동하면서 찾는 것.
큰 문제는 ㄷ 경로에서 생기게 된다

사람들의 아이디어 도움을 받아 해결..!
좌표를 2배 늘려 간단히 해결이 가능하다
👏🏻 할 일
- 크기가 2배인 격자 생성
- 직사각형의 둘레 설정
- BFS 알고리즘
격자 생성
크기가 2배가 되는 격자를 만들면 된다
격자의 기본값은 -1로 설정
board = [[-1 for _ in range(102)] for _ in range(102) ]
직사각형 둘레 설정
각 직사각형의 좌표를 2배로 설정한다
직사각형의 내부는 0으로, 둘레를 1로 설정
for rect in rectangle:
x1, y1, x2, y2 = map(lambda x: x*2, rect)
for x in range(x1, x2+1):
for y in range(y1, y2+1):
if x1< x < x2 and y1< y < y2:
board[x][y] = 0
elif board[x][y] != 0:
board[x][y] = 1
BFS
4방향으로 움직이도록 설정
현재지점이 도착지점이 된다면 cnt 출력
# 좌 우 위 아래
dx = [1, -1, 0, 0]
dy = [0, 0, 1, -1]
q = deque()
q.append((characterX*2, characterY*2))
visited = [[1] * 102 for _ in range(102)]
while q:
x, y = q.popleft()
if x == itemX*2 and y == itemY*2:
answer = visited[x][y] // 2
break
for d in range(4):
nx = x + dx[d]
ny = y + dy[d]
if board[nx][ny] == 1 and visited[nx][ny] == 1:
visited[nx][ny] += visited[x][y]
q.append((nx,ny))
코드
from collections import deque
def solution(rectangle, characterX, characterY, itemX, itemY):
# 크기가 2배인 격자 설정
board = [[-1 for _ in range(102)] for _ in range(102) ]
answer = 0
# 직사각형 둘레 설정
for rect in rectangle:
x1, y1, x2, y2 = map(lambda x: x*2, rect)
for x in range(x1, x2+1):
for y in range(y1, y2+1):
if x1< x < x2 and y1< y < y2:
board[x][y] = 0
elif board[x][y] != 0:
board[x][y] = 1
# 좌 우 위 아래
dx = [1, -1, 0, 0]
dy = [0, 0, 1, -1]
q = deque()
q.append((characterX*2, characterY*2))
visited = [[1] * 102 for _ in range(102)]
#BFS
while q:
x, y = q.popleft()
if x == itemX*2 and y == itemY*2:
answer = visited[x][y] // 2
break
for d in range(4):
nx = x + dx[d]
ny = y + dy[d]
if board[nx][ny] == 1 and visited[nx][ny] == 1:
visited[nx][ny] += visited[x][y]
q.append((nx,ny))
return answer
'프로그래밍 > Python' 카테고리의 다른 글
[프로그래머스] 전력망 둘로 나누기 / 완전탐색 / python (0) | 2024.03.13 |
---|---|
[프로그래머스] 피로도 / 완전탐색 / python (0) | 2024.03.12 |
[프로그래머스] 징검다리 / 이진 탐색 / python (0) | 2024.03.07 |
[프로그래머스] 입국심사 / 이진 탐색 / python (0) | 2024.02.14 |
[코드트리] 포탑 부수기 / 파이썬(Python) (0) | 2023.11.02 |
댓글