문제
https://school.programmers.co.kr/learn/courses/30/lessons/67259
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
풀이
풀이 1
BFS 알고리즘을 기반으로 작성하되, 코너와 직선 도로의 경우를 구분하기 위해 방향에 대한 정보(d)를 queue에 추가적으로 넣어 구분.
이미 지난 길이라도, 더 적은 비용으로 갱신할 수 있는 경우에 갱신하도록 코드를 구현하였다.
def solution(board):
from collections import deque
d = ''
n = len(board)
answer = []
q = deque([(0,0,d)])
while q:
x,y,d = q.popleft()
for nx,ny in [(x-1,y),(x,y+1),(x+1,y),(x,y-1)]:
if not (nx==0 and ny==0) and (0<=nx<n and 0<=ny<n) and board[nx][ny]!=1:
if (d=='h' and x!=nx) or (d=='v' and y!=ny): # corner
nd = 'h' if d=='v' else 'v'
if board[nx][ny]==0:
board[nx][ny] = board[x][y]+600
q.append((nx,ny,nd))
elif board[nx][ny]>=board[x][y]+600:
board[nx][ny]=board[x][y]+600
q.append((nx,ny,nd))
else: # straight
nd = 'h' if ny!=y else 'v'
if board[nx][ny]==0:
board[nx][ny] = board[x][y]+100
q.append((nx,ny,nd))
elif board[nx][ny]>=board[x][y]+100:
board[nx][ny] = board[x][y]+100
q.append((nx,ny,nd))
answer = board[n-1][n-1]
return answer
채점한 결과 몇개 케이스에서 오답으로 처리되었고, 조금 찾아보니 다음과 같은 테스트 케이스에서 오류가 발생하는 것을 알 수 있었다.
`[[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 0, 1, 0, 0], [1, 0, 0, 0, 1], [1, 1, 1, 0, 0]]`
정답은 3000이지만 3300이 출력되었고, 위의 알고리즘은 무조건 최소값을 기준으로 그래프를 갱신하지만 당장은 최소값이 아닐지라도 다음에 탐색할 위치에 대해서는 최소값이 생기는 경우가 발생하는 것을 확인할 수 있었다.
위의 예시의 (3,2)위치에서의 최소 비용은 2000이고 (2,3)에서의 최소 비용은 1700이며,
위 알고리즘에 따르면 (3,3)의 값은 2000+100 < 1700+600 이므로, (3,2) -> (3,3)의 경로의 비용인 2100으로 갱신된다.
하지만 (3,2) -> (3,3) -> (4,3)으로 가는 경로의 최소 비용은 2000+100+600 = 2700인데 반해,
(2,3) -> (3,3) -> (4,3)으로 가는 경로의 최소 비용은 1700+600+100 = 2400으로 결과적으로는 더 큰 비용의 값으로 갱신된다.
풀이 2
따라서, 종/횡의 방향 모두에서 접근해 오는 경우에는, 각 방향으로 부터의 비용값을 dictionary에 저장해놓기로 하고 다시 알고리즘을 작성하게 되었다.
def solution(board):
from collections import deque
d = ''
n = len(board)
answer = []
board[0][0] = {'':0}
q = deque([(0,0,d)])
while q:
x,y,d = q.popleft()
for nx,ny in [(x-1,y),(x,y+1),(x+1,y),(x,y-1)]:
if not (nx==0 and ny==0) and (0<=nx<n and 0<=ny<n) and board[nx][ny]!=1:
if (d=='h' and x!=nx) or (d=='v' and y!=ny): # corner
nd = 'h' if d=='v' else 'v'
if board[nx][ny]==0:
board[nx][ny] = dict()
board[nx][ny][nd] = board[x][y][d]+600
q.append((nx,ny,nd))
else:
if not board[nx][ny].get(nd):
board[nx][ny][nd] = board[x][y][d]+600
q.append((nx,ny,nd))
elif board[nx][ny][nd]>board[x][y][d]+600:
board[nx][ny][nd]=board[x][y][d]+600
q.append((nx,ny,nd))
else: # straight
nd = 'h' if ny!=y else 'v'
if board[nx][ny]==0:
board[nx][ny] = dict()
board[nx][ny][nd] = board[x][y][d]+100
q.append((nx,ny,nd))
else:
if not board[nx][ny].get(nd):
board[nx][ny][nd] = board[x][y][d]+100
q.append((nx,ny,nd))
elif board[nx][ny][nd]>board[x][y][d]+100:
board[nx][ny][nd]=board[x][y][d]+100
q.append((nx,ny,nd))
answer = min(board[n-1][n-1].values())
return answer
'알고리즘' 카테고리의 다른 글
[Python] 프로그래머스 - 징검다리 건너기 (1) | 2024.11.28 |
---|---|
[Python] 프로그래머스 - 호텔 방 배정 (0) | 2024.11.27 |
[Python] 프로그래머스 - 섬 연결하기 (0) | 2024.11.26 |
[Python] 프로그래머스 - 줄 서는 방법 (1) | 2024.11.20 |
[Python] 프로그래머스 - 보석 쇼핑 (2) | 2024.11.05 |