BFS/DFS 문제 풀이를 익히기 위해 미로 탈출 문제를 풀었다. Lv.2에 이전에 백준에서 많이 풀어봤던 느낌이라 쉽게 접근하고 풀 수 있었다. 어제 풀었던 문제를 떠올리면서 힌트를 얻기도 했다.
문제 설명
문자열의 배열로 주어진 미로에서 레버를 찍고 출구까지 가는 최단 거리를 구하는 문제이다.
상, 하, 좌, 우로 이동할 수 있으며 (대각선 불가)
output으로는 몇 칸을 이동했는지를, 탈출할 수 없으면 -1을 반환한다.
문제 해결
인접한 칸을 방문하면서 최단 거리를 구하는 문제라 BFS를 사용했다.
가장 먼저 구한 답이 최단 거리가 될 것이다.
DFS로 푼다면 모든 경우의 수를 다 구하기 때문에 비효율적임
일단 레버를 찍고 탈출구로 갈 수 있으므로 레버까지의 BFS 한 번, 출구까지의 BFS 한 번으로 목적지에 따라 두 번 나누어 풀었다.
목적지까지 가면서 방문하는 칸을 큐에 넣고 distance를 증가시켜 visited 역할도 한 번에 하도록 했다.
하나의 목적지에 도달하면 거기부터 다시 최단경로를 찾기 때문에 distance를 초기화해줬다.
주의 사항: 문제의 제한사항을 잘 읽어보자
"출구는 레버가 당겨지지 않아도 지나갈 수 있으며, 모든 통로, 출구, 레버, 시작점은 여러 번 지나갈 수 있습니다."
풀이 코드
from collections import deque
def bfs(maps, start, target):
h = len(maps)
w = len(maps[0])
q = deque()
q.append(start)
dist = [[0 for i in range(w)] for j in range(h)]
direction = [[0, -1], [1, 0], [-1, 0], [0, 1]]
while (q):
cur = q.popleft()
y = cur[0]
x = cur[1]
for d in direction:
if 0 <= x + d[1] < w and 0 <= y + d[0] < h:
dx = x + d[1]
dy = y + d[0]
if dist[dy][dx] == 0:
if maps[dy][dx] == target:
dist[dy][dx] = dist[y][x] + 1
return [dy, dx], dist[dy][dx]
elif maps[dy][dx] != "X":
dist[dy][dx] = dist[y][x] + 1
q.append([dy, dx])
return [], -1
def solution(maps):
start = []
for i in range(len(maps)):
if "S" in maps[i]:
start = [i, maps[i].find("S")]
target = ["L", "E"]
answer = 0
for t in target:
start, dist = bfs(maps, start, t)
if dist == -1:
return -1
answer += dist
return answer
먼저 start 좌표를 찾아서 탐색을 시작한다. 첫 번째 타겟인 레버를 만나면 레버의 좌표와 현재까지 거리를 반환한다. 레버의 좌표부터 다시 탐색을 시작해 출구를 만나면 모든 거리를 더해준다.
헤맸던 점
1. return 값의 형식을 통일하지 않아서
여러 오류를 마주했고 구글링 헛수고 하다가 문득 코드 오류 발견하고 해결했다. 그동안 많이 못 봤던 에러라서 정리를 해보겠다.
TypeError: cannot unpack non-iterable int object
반복이 불가능한 int 객체를 unpack할 수 없다는 에러.
풀이 코드에서 return 값을 튜플로 설정해서 unpacking 하는 과정에서 발생한 것으로 추정.
TypeError: 'int' object is not subscriptable
int형을 인덱싱 및 슬라이싱할 때 발생하는 에러.
이 에러 역시 풀이 코드에서는 좌표와 거리의 return 값을 리스트로 주고 있는데 답이 없을 때는 return 값을 -1로 설정해 solution 함수에서 인덱스로 접근했다가 마주한 에러였다.
너무 기초적이라서 쉽게 볼 수 없었던 이유가 있는 에러들이었다 ㅎㅎ.. 혹시 다시 만나게 된다면 바로 해결할 수 있겠다!
2. "O"인 칸만 큐에 넣어서
프로그래머스 질문하기에서 Jay EPH님의 글을 보고 아차 싶었다.
방문할 수 없는 노드를 제외하고는 방문할 수 있도록 해서 바로 해결했다.
밑의 예시를 보면 바로 이해가 된다!
# input
["SELXX", "XXXXX", "XXXXX", "XXXXX", "XXXXX"]
# output
-1
# correct
3
x, y 좌표가 스스로 헷갈리기도 하고 뜬금없는 오류에 시간을 좀 썼지만 난이도는 쉬웠던 문제였다. 풀이가 눈에 보이면 보이는대로 재밌고 너~무 모르겠으면 그런대로 다른 풀이 방법을 찾아 공부하는 재미가 있다. 방학이 3주 정도 남았고 며칠간 코딩을 할 수가 없어서 아쉽다.. 얼른 다른 재밌는 문제들도 풀고 싶다. 다음 주부터 다시 열심히 풀어야지!
'알고리즘' 카테고리의 다른 글
[SWEA] 1206. View (S/W 문제해결 기본 - 1일차) / Python 코드 (0) | 2024.05.17 |
---|---|
[프로그래머스] 가장 먼 노드 / 그래프, DFS, BFS / Python 코드 (0) | 2024.02.12 |
[프로그래머스] 오픈채팅방 / 2019 Kakao / Python 코드 (2) | 2024.02.10 |
[프로그래머스] 디스크 컨트롤러 / Heap / Python 코드 (2) | 2024.02.09 |
[BOJ] 9466. 텀 프로젝트 / DFS / Python 풀이 (0) | 2023.06.11 |