문제 분석
- 두 팀으로 나눠서 진행
- 상대 팀 진영을 먼저 파괴하면 이기는 게임
- 각 팀 진영에 최대한 빨리 도착하는 것이 유리
- 갈 수 없는 길 & 갈 수 있는 길
- 한 번에 한 칸 동서남북으로 이동 가능
- 상대 팀이 다 막혀있다면 상대 팀 진영에 가지 못할 수도 있음
- 상대 팀 진영에 도착하기 위해 가야하는 최솟값 return
- 상대 팀 진영에 도착할 수 없다면 -1 return
- maps 크기 : n x m
- 0 : 갈 수 없는 자리
- 1 : 갈 수 있는 자리
- 처음 캐릭터는 좌측 상단 (1,1)에 위치 (인덱스로 하면 (0,0))
- 상대방 진영은 게임 맵 우측 하단 (n,m)에 위치 (인덱스로 하면 (n-1, m-1)
코드 설계
- maps 입력
- 갈 수 있는 경우는 맵 내부, 해당 자리의 값이 1인 경우
- return 조건
- (n,m) 위치에 도달하는 경우 : return 현재까지 이동한 거리
- 전부 탐색했는데 만나지 못한 경우 : return -1
- 깊이 우선 ? 너비 우선 ?
정답 코드
1차 코드 - 실패
from collections import deque
def solution(maps):
n = len(maps)
m = len(maps[0])
g = maps
d = deque()
v = [[False] * m for _ in range(n)]
# 해당 인덱스의 값이 0이면 갈 수 없는 자리
for i in range(len(maps)):
for j in range(len(maps[0])):
if maps[i][j] == 0:
v[i][j] = True
dh = [-1, 1, 0, 0]
dw = [0, 0, -1, 1]
d.append((0, 0, 0))
v[0][0] = True
while d:
h, w, distance = d.popleft() # 현재 위치 인덱스
if h == n - 1 and w == m - 1:
# 현재 위치 제외 ?
return distance-1
# 다음 위치로 이동할 수 있는가
for k in range(4):
nh = h + dh[k]
nw = w + dw[k]
# 1. 범위를 벗어나지 않는가
if nh < 0 or nh >= n or nw < 0 or nw >= m:
continue
# 2. 이동하려는 인덱스의 값이 1인가
if g[nh][nw] != 1:
continue
# 3. 이동하려는 인덱스를 아직 방문하지 않았는가 (v[i][j] == False 인가)
if v[nh][nw]:
continue
distance += 1
v[nh][nw] = True
d.append((nh, nw, distance))
return -1
- distance가 반복문 안에서 증가 : 이로 인해 노드에서 여러번 방문할 때 잘못된 값으로 누적될 수 있음
- distance가 각 경로별로 개별 관리되어야 함
2차
from collections import deque
def solution(maps):
n = len(maps)
m = len(maps[0])
# g = []
g = maps
d = deque()
v = [[False] * m for _ in range(n)]
# 해당 인덱스의 값이 0이면 갈 수 없는 자리
for i in range(len(maps)):
for j in range(len(maps[0])):
if maps[i][j] == 0:
v[i][j] = True
# else :
# v[i][j] = False
dh = [-1, 1, 0, 0]
dw = [0, 0, -1, 1]
d.append((0, 0, 1))
v[0][0] = True
# answer += 1
while d:
h, w, distance = d.popleft() # 현재 위치 인덱스
if h == n - 1 and w == m - 1 :
return distance
# 다음 위치로 이동할 수 있는가
for k in range(4):
nh = h + dh[k]
nw = w + dw[k]
# 1. 범위를 벗어나지 않는가
if nh < 0 or nh >= n or nw < 0 or nw >= m:
continue
# 2. 이동하려는 인덱스의 값이 1인가
if g[nh][nw] != 1:
continue
# 3. 이동하려는 인덱스를 아직 방문하지 않았는가 (v[i][j] == False 인가)
if v[nh][nw]:
continue
v[nh][nw] = True
d.append((nh, nw, distance+1))
return -1
1.
v[nh][nw] = True
d.append((nh, nw, distance+1))
vs
2.
distance += 1
v[nh][nw] = True
d.append((nh,nw, distance))
1 :
- 이동할 때마다 현재 노드 거리 + 1의 값을 큐에 추가된다. distance의 거리가 매번 새로 계산된다.
- bfs 탐색은 큐에 담긴 각 노드의 경로가 독립적으로 유지된다.
- 따라서 경로마다 별개의 distance가 정확하게 관리된다.
2 :
- distance 변수가 전역처럼 누적되며 증가한다.
- 모든 경로에서 동일한 distance 변수를 사용하기 때문에 큐에 담긴 다른 경로에도 영향을 미친다.
- 따라서 한 번 방문한 노드를 재방문하지 않는데 다른 경로에서 계산된 distance가 더해지는 즉, 불필요한 거리가 더해지는 문제가 발생한다.
'코딩 테스트 > 프로그래머스' 카테고리의 다른 글
[Python] 프로그래머스 lv.0 카운트다운 (0) | 2024.10.23 |
---|---|
[Python] 프로그래머스 lv.0 글자 지우기 (0) | 2024.10.23 |
[Python] 프로그래머스 lv.0 문자 개수 세기 (1) | 2024.10.22 |
[Python] 프로그래머스 lv.0 qr code (0) | 2024.10.21 |
[Python] 프로그래머스 lv.0 세로 읽기 (0) | 2024.10.21 |