티스토리 뷰
📍 문제 탐색하기
개구리가 일렬로 놓인 징검다리 사이를 배수 단위로 점프하면서 시작 지점 a에서 목표 지점 b까지 도달하는 최소 점프 횟수를 구하는 문제다.
특정 징검다리에 쓰인 숫자를 k라고 하면, k는 그 위치에서 점프할 수 있는 단위를 의미하며, 배수(±k,2k,3k,...)의 형태로만 이동이 가능하다.
- 입력 범위:
- 징검다리 개수 N: 최대 10,000
- 각 징검다리에 쓰인 숫자 k: 최대 10,000
- a,b: 시작점과 도착점으로 1 ≤ a,b ≤ N
가능한 시간복잡도
문제를 해결하기 위해 a에서 b까지 탐색해야 한다.
O(N):
: 즉 최대 10,000번의 방문과 연산이 일어난다. 따라서 1억 연산 이하로 충분히 제한 시간 안에 처리가 가능하다.
BFS를 이용하여 배수 형태로 이동 가능한 경로만을 탐색하면 효율적으로 해결할 수 있다.
알고리즘 선택
O(N)으로 처리가 가능하고, 최소 몇 번 점프했는지를 구해야하는 문제이므로,
탐색 알고리즘 중에서 최단 경로를 찾는 데 적합한 너비 우선 탐색(BFS)를 선택했다.
BFS를 통해 문제에서 요구하는 최소 점프 횟수를 효율적으로 구할 수 있다.
📍 코드 설계하기
- 문제의 Input을 받는다.
- 징검다리 개수 N과 각 징검다리에 적힌 숫자 배열을 정의한다.
- BFS를 통해 시작점 a에서 목표 지점 b까지 탐색한다.
- 현재 위치에서 배수 단위로 이동 가능한 지점만 탐색하며 큐에 추가한다.
- 방향은 양방향(왼쪽, 오른쪽)을 모두 고려해야 한다. ->
이거 고려 안해서 틀렸다. ㅠㅠ
📍 시도 회차 수정 사항
1차 시도 (틀림) ❌
import sys
from collections import deque
input = sys.stdin.readline
N = int(input())
bridge = list(map(int, input().split()))
a, b = map(int, input().split())
visited = [False] * (N+1)
def bfs(start): # start: 위치
visited[start] = True
queue = deque([(start, 0)]) # 현재위치, 점프 횟수
while queue:
current, jump = queue.popleft()
if current == b:
return jump
num = bridge[current - 1] # 징검다리에 적힌 숫자
mul = 1
while True:
next_pos = current + num * mul
if next_pos > N:
break
if not visited[next_pos]:
queue.append((next_pos, jump + 1))
visited[next_pos] = True
mul += 1
return -1
result = bfs(a)
print(result)
오른쪽으로만 점프하도록 구현했다. 왼쪽 방향 탐색이 없어 틀렸다. 양방향 탐색을 구현해주어야 한다.
2차 시도 (맞음) ✅
import sys
from collections import deque
input = sys.stdin.readline
N = int(input())
bridge = list(map(int, input().split()))
a, b = map(int, input().split())
visited = [False] * (N+1)
def bfs(start): # start: 위치
visited[start] = True
queue = deque([(start, 0)]) # 현재위치, 점프 횟수
while queue:
current, jump = queue.popleft()
if current == b:
return jump
num = bridge[current - 1] # 징검다리에 적힌 숫자
mul = 1
while True:
next_pos = current + num * mul
if next_pos > N:
break
if not visited[next_pos]:
queue.append((next_pos, jump + 1))
visited[next_pos] = True
mul += 1
mul = 1
while True:
next_pos = current - num * mul
if next_pos < 1:
break
if not visited[next_pos]:
visited[next_pos] = True
queue.append((next_pos, jump + 1))
mul += 1
return -1
result = bfs(a)
print(result)
양방향 탐색을 구현했으나,
왼쪽, 오른쪽 점프 코드를 각각 작성하여 점프 방향별 코드가 중복되는 느낌이 들었다.
중복을 없애고 싶었다!
최종 코드 (맞음) ✅
import sys
from collections import deque
input = sys.stdin.readline
N = int(input())
bridge = list(map(int, input().split()))
a, b = map(int, input().split())
visited = [False] * (N+1)
def bfs(start): # start: 위치
visited[start] = True
queue = deque([(start, 0)]) # 현재위치, 점프 횟수
while queue:
current, jump = queue.popleft()
if current == b:
return jump
num = bridge[current - 1] # 징검다리에 적힌 숫자
for direction in [1, -1]:
mul = 1
while True:
next_pos = current + num * mul * direction
if next_pos < 1 or next_pos > N:
break
if not visited[next_pos]:
visited[next_pos] = True
queue.append((next_pos, jump + 1))
mul += 1
return -1
result = bfs(a)
print(result)
점프 방향(왼쪽, 오른쪽)을 변수화하여 중복 코드를 제거하였고, BFS를 통해 최소 점프 횟수를 정확히 계산할 수 있도록 최적화했다!
'알고리즘' 카테고리의 다른 글
[알고리즘] 백준 파이썬 27737 버섯 농장 (2) | 2025.01.08 |
---|---|
[알고리즘] 백준 4963 섬의 개수 파이썬 (0) | 2025.01.07 |
백준 파이썬 1431 시리얼 번호 (3) | 2024.03.13 |
백준 파이썬 1713 후보 추천하기 (0) | 2024.02.29 |
백준 파이썬 5212 지구 온난화 (1) | 2024.02.27 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 웹MVC
- 커뮤니티
- 스프링부트
- 스프링
- SQL
- JPA
- 회원탈퇴
- 백준
- 자바 스프링
- SQLD
- DP
- 영속
- 프론트엔드
- SQL 레벨업
- 스프링 북마크
- 로그아웃
- EnumType.ORDINAL
- 준영속
- 다이나믹 프로그래밍
- 파이썬
- 백준 파이썬
- 웹 MVC
- 스프링 커뮤니티
- 로깅
- elasticsearch
- 인텔리제이
- 자바
- 지연로딩
- 비영속
- 북마크
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함