티스토리 뷰
문제
수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 0초 후에 2*X의 위치로 이동하게 된다.
수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오.
입력
첫 번째 줄에 수빈이가 있는 위치 N과 동생이 있는 위치 K가 주어진다. N과 K는 정수이다.
출력
수빈이가 동생을 찾는 가장 빠른 시간을 출력한다.
처음에는 다익스트라로 접근했습니다. heapq를 사용하면 바로 풀 수 있을 것으로 생각했습니다. 결론적으로 말씀드리자면, 풀 수 있습니다. 근데 시간이 좀 많이 오래걸리네요. 도중에 더 좋은 풀이가 없을지 찾아보았습니다. python은 워낙 코테 풀이가 좋아서 deque로 풀 수 있는 방법이 있드라구요. 그래서 오늘은 제가 풀이한 코드와 많이 돌아다니는 풀이를 2개 모두 알아볼까 합니다.
참고로 어떤 풀이가 더 좋은가? 에 대해서는 독자들이 판단하는게 좋을거 같습니다. 전 솔직히 많이 돌아다니는 풀이가 더 좋은 것 같습니다. 이유는 문제에서 요구하는 부분을 잘 파악하고 짠 느낌이 들어요. 그렇기 때문에 더 효율적인 코드가 나온게 아닌가? 하는 느낌도 많았습니다.
일단 문제에서 요구하는 것은 수빈이가 동생이 있는 지점까지 갈 때 가장 짧은 거리가 몇인지를 구하는 문제였습니다.
각 점에서 이동할 수 있는 지점이 정해져있다는 것은 문제 풀이에 가장 큰 영향을 미치고 있습니다. 갈 수 있는 지점에 아에 정해져 있어서 그 부분만 보면 되거든요. 이런 부분은 약간 자료구조를 선형적으로 가져가도 된다는 의미로 생각할 수 있지 않을까요? 그래서 많이 돌아다니는 풀이는 코드 길이가 정말 짧아요. 그리고 엄청 효율적이죠.
많이 돌아다니는 풀이
from collections import deque
n, k = map(int,input().split())
node = [-1 for _ in range(100001)]
node[n] = 0
q = deque()
q.append(n)
while q:
now = q.popleft()
if now == k:
print(node[now])
break
if 0 < 2*now < 100001 and node[2*now] == -1: # 1번, 가장 먼저 수행해야 가장 빠른 길을 찾을 수 있음.
node[2*now] = node[now]
q.appendleft(2*now)
if 0 <= now + 1 < 100001 and node[now+1] == -1:
node[now+1] = node[now] + 1
q.append(now+1)
if 0 <= now - 1 < 100001 and node[now-1] == -1:
node[now-1] = node[now] + 1
q.append(now-1)
1번 코드가 제일 중요합니다. 해당 코드에서 나타내는 것은 큐 자료구조에서도 우선순위를 가리겠다는 의미를 지니고 있거든요. 그래서 순간이동을 하는 가장 적은 비용을 수반하는 코드가 가장 먼저 실행될수 있도록 가장 먼저 q담도록 하고 있습니다. 그리고 또 저는 지금껏 사용하지 않은 method인 appendleft()를 사용했습니다. popleft()처럼 deque에서 사용할 수 있을 때 많이 사용해야겠습니다. 여튼 위 풀이의 가장 큰 장점은 비용이 0인 순간이동을 가장 먼저 실행하고 찾기 때문에 가장 비용이 적은 답을 빠르게 찾을 수 있다는 것입니다.
나의 풀이
from heapq import heappop, heappush
n, k = map(int, input().split())
node = [[] for _ in range(1000002)]
for i in range(100001): # 2번: 그래프 생성
if i <= 50000:
node[i].append((2*i, 0))
node[i].append((i-1, 1))
node[i].append((i+1, 1))
def dijkstra(s, e, node):
INF = 100000
dist = [INF for _ in range(1000002)]
dist[s] = 0
q = []
heappush(q, (0, s))
while q:
distance, now = heappop(q)
if dist[now] < distance:
continue
for nxt, dis in node[now]:
cost = dis + distance
if cost < dist[nxt]:
dist[nxt] = cost
heappush(q, (cost, nxt))
return dist[e]
print(dijkstra(n, k, node))
제 풀이는 정말 가장 정형적인 풀이에요. graph를 구성하고 dijkstra 돌리기.. 맨 처음에 graph를 어떻게 구성해야 하나 생각했습니다. 그래서 2번과 같은 코드가 나온 것이죠. 그리고 그냥 다익스트라 돌렸습니다. 무지성이었죠... 그래서인지 풀이 결과를 비교하면 다음과 같아요... 약간 충격적입니다.

네.. 속도가 거의 4~5배 차이가 납니다. 문제의 제한시간이 2초였기 때문에, 둘 다 별 상관없는 풀이긴 하지만, 그래도 전 약간 충격이네요. 최근들어서 다시 알고리즘 풀이를 시작했는데, 정진해야겠다는 생각을 하게됩니다. 사실 요새 구현 문제를 많이 풀었습니다...ㅋㅋㅋ
다음에 또 올리겠습니다! 화이팅!
'알고리즘 > BeakJoon' 카테고리의 다른 글
| [BOJ] 구간 합 구하기 4 in Kotlin (0) | 2021.12.14 |
|---|---|
| [BOJ] 구간 합 구하기 4 in Python (0) | 2021.12.13 |
| [BOJ] 구간 합 구하기 5 (0) | 2021.12.10 |
| [BOJ] 청소년 상어 (0) | 2021.12.03 |
| [BOJ] 2468 안전 영역 in Python (0) | 2021.11.12 |
- Total
- Today
- Yesterday
- Programmers #알고리즘 #Python #KAKAOINTERNSHIP #비전공개발자 #불량사용자
- 백준알고리즘 #BFS #델타이동 #알고리즘풀이 #개발 #안전영역 #풀스택개발자가되고싶습니다. #노력할래요 # 꾸준히 # 화이팅! #비전공개발자
- 구간 합 구하기 4
- 백준
- 비전공싸피합격
- 프로젝트구조
- DP
- 참조연산자
- Class
- 안드로이드
- 일반파라미터
- 알고리즘
- Java #객체지향 #상속 #생성자 #개념 #비전공개발자 #FullStack을 #향해
- Java
- Python
- 생성자
- 코틀린
- 프로그래머스
- 비전공개발자
- 안드로이드 #안드로이드스튜디오 #Kotlin #앱개발 #안드로이드기초 #비전공개발자 #풀스택개발자 #앱개발자
- 기본생성자
- Kotlin
- 중첩클래스와 내부클래스
- 추가합격후기
- 싸피5기
- 백준 #숨박꼭질3 #다익스트라 #알고리즘 #비전공개발자 #풀스택 #웹개발 #앱개발 #안드로이드 #python
- 카카오
- 앱개발
- kotlin문법
- 보조생성자
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
