티스토리 뷰
문제주소
programmers.co.kr/learn/courses/30/lessons/67259
내 풀이
answer = 10e9
def dfs(board, pos, n, cost_board):
x, y = pos[0][0], pos[0][1]
dir = pos[1]
cost = pos[2]
global answer
# 종료조건
# 끝지점 도착
if pos[0] == (n, n):
answer = min(answer, pos[2] * 100)
return
# cost 가 answer보다 커지는건 최솟값이 아니므로 종료
if cost > answer:
return
# cost_board에 저장된 값이 지금 cost 보다 작다는 것은 이미 방문한 곳이고, 이미 최솟값이므로 종료
if cost_board[x][y] < cost:
return
direction = [0, 1, 2, 3]
dx = [0, 1, 0, -1]
dy = [1, 0, -1, 0]
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
nd = direction[i]
if board[nx][ny] == 0 :
# 방향이 같은 경우
if nd % 2 == dir % 2:
curr = ((nx, ny), dir, cost + 1)
cost_board[nx][ny] = min(cost_board[nx][ny],cost + 1) # 이렇게 min값으로 갱신
# 방향이 다른 경우
if nd % 2 != dir % 2:
curr = ((nx, ny), nd, cost + 6)
cost_board[nx][ny] = min(cost_board[nx][ny],cost + 6) # 이렇게 min값으로 갱신
dfs(board, curr, n, cost_board)
def solution(board):
n = len(board)
new_board = [[1] * (n + 2) for _ in range(n + 2)]
for i in range(n):
for j in range(n):
new_board[i + 1][j + 1] = board[i][j]
#시작에서 오른쪽으로 가는경우, 아래로 가는경우 2가지 모두 진행
start_s = ((1, 1), 1, 0)
start_c = ((1, 1), 0, 0)
cost_board = [[10e9] * (n + 2) for _ in range(n + 2)]
dfs(new_board, start_s, n, cost_board)
dfs(new_board, start_c, n, cost_board)
return answer
우와... 너무 어려웠다. 처음에 bfs로 도전했다가 안되서 dfs로 도전했는데 뒤에 테스트케이스가 통과가 안되었다. 안되는 이유를 찾아가며, 사실 인터넷에서 다른 풀이도 좀 참고하며 개선해나갔다.
1. 첫번째문제
dfs 리턴을 해주는 방식이 안되서 global을 사용하여 값을 갱신해주는 방식으로 했다. 재귀를 사용하는게 아직 좀 어렵다. return dfs를 하게되면 끝까지 탐색이 안되고 종료되어 버려서 호출을 해주어야 answer 값까지 도달 가능했다.
2. 계속 참조하는 인자(board)의 값!
dfs에 인자로 들어가는 new_board, cost_board 등은 계속 참조되는 값이다! 처음에는 visited나 new_board에 그대로 방문처리를 하는 것으로 하려했는데 계속 참조되는 값이라 한번 등록하면 변경이 안되었다. 계속 값을 가지고 다니는데 루트별로 다르게 값을 가져야했다. 그래서 다음에 시도했던 것이 copy.deepcopy(new_board)로 매번 copy한 값을 넘겨주는 것이었다. 매번 객체생성이 되어서 시간이 너무 오래걸린다ㅠㅠㅠ visited[:]로 copy 해주는 값을 줄여보려고 했지만 여전히 매번 복사해서 값을 가지고 다니는 것은 문제가 있다ㅠㅠ
여기까지 하다가 계속 막혀서 결국 인터넷에서 다른 dfs 풀이를 참고했다. 나의 코드에 아이디어를 적용해보았다. cost_board를 만들어서 가장 최소 cost를 갱신해주는 방식으로 했다. 이경우, min 메소드를 cost를 갱신해주어야 했고, 재귀의 종료조건을 잘 설정해주어야 했다. visited를 사용하기 까다로워서 최소값을 갱신하며 가지고 다니게 했더니 드디어 통과가 되었다!! 🎉
다른 사람 풀이
BFS로 푼 방식이 많은 듯 싶다. 힌트를 보려다가 다익스트라로 푸는 경우도 있는 것 같은데.. 스터디하면서 다른 풀이를 좀 더 참고해 봐야겠다. 어렵다..😅
정리
DFS와 BFS를 더 공부해야겠다는 생각이 더더욱 들었다. BFS에서는 queue를 DFS는 재귀를 많이 사용하는 것 같다. 어떤 값을 넣어주고, visited를 어떻게 처리할 것인지, 어떻게 종료할 것인지가 중요하다. ⚡
특히 이 문제는 어떻게 인덱싱하여 값을 사용할 것인지가 중요한 듯 하다. 어떻게 값을 가져올 것인지, 종료조건을 어떻게 설정할 것인지! 잘 생각하자! 재귀를 사용하는 것은 계속 참조되는 값(특히 배열)과 종료조건!에 유의하자!✔
'Algorithm > 문제풀이 Python' 카테고리의 다른 글
최소공배수, 최대공약수(유클리드호제법), 소수(에라토스테네스의 체), n진수 만들기 (0) | 2021.08.23 |
---|---|
[꿀팁] 2차원 배열(N*N) 행,열 쉽게 뒤집기 (0) | 2021.08.21 |
프로그래머스 레벨3 - 카카오 2020인턴 보석쇼핑 (0) | 2021.02.02 |
프로그래머스 레벨3 - 카카오 2019인턴 징검다리건너기 (0) | 2021.01.30 |
프로그래머스 레벨3 - 카카오 2018 셔틀버스 (0) | 2021.01.26 |
- Total
- Today
- Yesterday
- 우테코수업
- java
- 카카오
- 인증
- Transaction
- 객체지향
- CS
- 학습로그
- 알고리즘
- React
- Spring
- 회고
- 마스터즈코스
- 월간회고
- 내부코드
- 네트워크
- TIL
- 글쓰기미션
- 운영체제
- TCP/IP
- JS
- 코드스쿼드
- 개발공부일지
- python
- JPA
- DB
- 모의면접준비
- 우아한테크코스
- javascript
- OS
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |