일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 파이썬
- Python
- 자바스크립트
- JetsonNano
- 코테
- 우아한테크코스
- npm
- 백준
- express
- 그리디
- dfs
- 프로그래머스
- Linux
- 함수
- BFS
- 우테코
- node.js
- 웹개발
- 알고리즘
- Sort
- 코딩테스트
- 고득점kit
- 프리코스
- 그래프
- 프론트엔드
- 최단거리
- 문자열
- JS
- JavaScript
- OpenCV
- Today
- Total
공대생
백준 1697 숨바꼭질 Python ✔ 본문
✔ : 풀이참고. 다시 풀어야 봐야 할 문제
문제설명
수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 1초 후에 2*X의 위치로 이동하게 된다.
수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오.
제한사항
- N(0 ≤ N ≤ 100,000)
- K(0 ≤ K ≤ 100,000)
입력
첫 번째 줄에 수빈이가 있는 위치 N과 동생이 있는 위치 K가 주어진다. N과 K는 정수이다.
출력
수빈이가 동생을 찾는 가장 빠른 시간을 출력한다.
예제
이 문제의 key포인트
-> 수빈이가 동생을 찾는 가장 빠른 시간을 출력한다.
예제를 보면 알 수 있듯이, 가장 빠른 시간이라고 동생의 위치에 가까워질 때까지 무작정 순간이동을 시키면 안된다.
EX ) N = 5, K = 17
무작정 순간이동: 5-10-20-19-18-17 -> 5초
정답: 5-10-9-18-17 -> 4초따라서 수빈이가 현재 있는 곳에서 갈 수 있는 지점을 모두 고려해야 한다. -> BFS 사용
자료구조 및 알고리즘: BFS + DP
문제풀이
첫번째 풀이
코드(틀린코드, 5%에서 메모리초과)
from collections import deque
N, K = map(int, input().split())
# 수빈이가 갈 수 있는 곳 다 찾기
queue = deque([])
def BFS():
queue.append([N, 0]) # 수빈이 위치, 간 거리
while queue:
cur, cnt = queue.popleft()
if cur == K: # 동생을 찾으면 중지
print(cnt)
break
queue.append([2 * cur, cnt + 1]) # 순간이동
queue.append([cur + 1, cnt + 1]) # 걷기
queue.append([cur - 1, cnt + 1]) # 걷기
BFS()
수빈이가 현재 있는 곳이 5이면 수빈이가 갈 수 있는 곳은 [10, 6, 4] 이고
- 수빈이가 10으로 갔을 때 갈 수 있는 곳은 [20, 11, 9]
- 수빈이가 6으로 갔을 때 갈 수 있는 곳은 [12, 7, 5]
- 수빈이가 4로 갔을 때 갈 수 있는 곳은 [8, 5, 3]
이런 식으로 나뭇가지 모양으로 갈 수 있는 곳을 다 찾고 찾는 도중에 동생의 위치로 갔을 때 찾는 것을 중지하고 찾는데까지 걸린 시간을 출력하도록 하였다.
예제는 정답이 나왔지만 메모리초과가 났다.
deque문제인가 싶어서 queue를 list로 바꾸고 popleft() 대신 pop(0)을 사용했더니 시간초과가 났다.
두번째 풀이
코드(완성코드, 맞았습니다!!, 152ms)
# BOJ 1697 숨바꼭질
# 152ms
# 34692KB
from collections import deque
N, K = map(int, input().split())
# 수빈이가 갈 수 있는 곳 다 찾기
queue = deque()
def BFS():
queue.append(N) # 수빈이 위치
while queue:
cur = queue.popleft()
# 동생위치 도착하면 함수 종료
if cur == K:
return
for i in (cur - 1, cur + 1, cur * 2):
# 메모이제이션
if 0 <= i < 100001 and dp[i] == 0:
dp[i] = dp[cur] + 1
queue.append(i)
dp = [0] * 100001
BFS()
print(dp[K])
메모리를 줄이는 방법을 떠올리지 못해서 다른 사람의 풀이를 참고했다.
DP에서 사용하는 메모이제이션을 쓴 것 같다. 방문처리를 이용한거라고 해도 좋을 것 같다. 위의 코드와 아이디어는 동일하지만 이 코드에서는 if문을 이용해 노드가 중복된 곳을 또 가지 않도록 막아주었다. 내 생각보다 중복되는 노드로 많이 갔나보다..
그리고 for문을 리스트가 아니어도 for i in (cur - 1, cur + 1, cur * 2) 이렇게 쓸 수 있다는 것도 알게되었다!
'스터디 > 백준' 카테고리의 다른 글
백준 1389 케빈 베이컨의 6단계 법칙 Python (0) | 2022.06.15 |
---|---|
백준 16928 뱀과 사다리 게임 Python (0) | 2022.06.14 |
백준 7576 토마토 Python ✔ (0) | 2022.06.10 |
백준 2178 미로탐색 Python (0) | 2022.06.07 |
백준 2667 단지번호붙이기 Python (0) | 2022.06.02 |