728x90
난이도 : Lv. 3
풀이일 : 2411295
https://school.programmers.co.kr/learn/courses/30/lessons/72413
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
문제
그림이 너무 크고 많아서 링크로 이동해서 문제를 확인하시길 추천드립니다.
아이디어
- 출발지에서 모든 도착지에 대해 다익스트라 알고리즘으로 최소 비용 탐색
- 반복문을 순회하며 모든 장소에서 a, b의 목적지까지 최소 비용 탐색하고 최소값 저장
전체 풀이 코드
import heapq
def solution(n, s, a, b, fares):
answer = int(1e9)
road = [[] for _ in range(n + 1)]
# 최소비용 탐색
def djikstra(start):
visited = [int(1e9)] * (n + 1)
visited[start] = 0
queue = []
heapq.heappush(queue, [0, start])
while queue:
cost, now = heapq.heappop(queue)
if cost <= visited[now]:
for add, after in road[now]:
if visited[after] > cost + add:
visited[after] = cost + add
heapq.heappush(queue, [cost + add, after])
return visited
# 입력 처리
for i in range(len(fares)):
start, end, cost = fares[i]
road[start].append([cost, end])
road[end].append([cost, start])
# 출발지에서 모든 도착지까지 최소 비용 탐색
together = djikstra(s)
# 각 도착지에서 A,B 최소 비용 탐색
for i in range(1, n + 1):
route = djikstra(i)
answer = min(together[i] + route[a] + route[b], answer)
return answer
상세 풀이 코드
import heapq
def solution(n, s, a, b, fares):
answer = int(1e9)
load = [[] for _ in range(n + 1)]
- answer : 최소 비용을 저장할 변수. 최초에는 큰 수로 설정
- load : 각 번호의 장소와 연결된 장소, 비용을 저장할 2차원 배열
# 최소비용 탐색
def djikstra(start):
visited = [int(1e9)] * (n + 1)
visited[start] = 0
queue = []
heapq.heappush(queue, [0, start])
while queue:
cost, now = heapq.heappop(queue)
if cost <= visited[now]:
for add, after in load[now]:
if visited[after] > cost + add:
visited[after] = cost + add
heapq.heappush(queue, [cost + add, after])
return visited
- 다익스트라 알고리즘 코드 구현
- visited : start에서 각 번호까지 드는 비용 기록, 최초에는 큰 값으로 설정
- 힙큐에 [비용, 장소] 추가
- 힙큐가 있는 동안, 비용과 현재 장소 pop
- 만약, 지금까지의 비용이 현재 경로에 저장된 비용보다 크다면, 최소비용이 될 수 없으므로 고려하지 않음
- add, after : 다음 경로까지의 비용, 다음 도착지 정보
- 만약 다음경로까지 기록된 최소비용 보다 현재 이동할 경로가 싸다면 visited[after] 재할당, 힙큐에 추가
- 최종적으로 모든 도착지에 대한 최소 비용을 저장한 visited 반환
# 입력 처리
for i in range(len(fares)):
start, end, cost = fares[i]
load[start].append([cost, end])
load[end].append([cost, start])
- 주어지는 경로 입력 처리 과정
- fares[i]에 담긴 출발지, 도착지, 비용 정보를 양방향 저장
# 출발지에서 모든 도착지까지 최소 비용 탐색
together = djikstra(s)
# 각 도착지에서 A,B 최소 비용 탐색
for i in range(1, n + 1):
route = djikstra(i)
answer = min(together[i] + route[a] + route[b], answer)
return answer
- together : 합승 택시 요금 계산. 출발지에서부터 모든 경로로의 다익스트라 탐색 진행
- for 반복문 : 출발지에서 이동한 모든 장소에서 새로 출발하여 다익스트라 탐색 진행
- route : 합승 후 출발지 i에서 모든 장소로의 최소 비용을 저장
- answer : 기록된 answer와 합승구간 비용, A, B의 합승 후 개인 이동 비용 중 작은 값 저장
느낀점
- 처음에는 A, B의 다익스트라 배열을 구해두고, 한 칸씩 따라가는 방식으로 코드를 짰는데, 반례가 생각나서 바꿨다.
- 모든 경로에 대해서 다익스트라 함수를 실행하고, 다시 모든 장소에서 출발하며 다익스트라 함수를 진행하면 너무 비효율적일거라고 생각했는데, 통과가 되어서 어디 고칠 데 없나 좀 들여다보고 수정했다.
- 우선, A, B의 비용을 한 번에 구할 수 있으니까 기존에는 route 선언 없이 djikstra를 구하던 방식에서 한 번 함수 실행 결과를 저장하고 a, b 최소 비용을 가져오는 방식으로 수정했다. 시간이 절반 정도로 줄어든 것들도 있어서 조금 뿌듯한 상태
- 자바로도 풀어보고 싶은데 아직 너무 어려운 것 같다ㅠ
성능 비교
- 왼쪽 코드가 마지막 for 반복문에서 djikstra 두 번 부를 때, 오른쪽 코드가 한 번 부를 때 시간이다.
'알고리즘 > Lv. 3' 카테고리의 다른 글
프로그래머스 87694 아이템 줍기 자바 풀이 (0) | 2024.12.18 |
---|---|
프로그래머스 87694 아이템 줍기 파이썬 풀이 (0) | 2024.12.18 |
프로그래머스 43163 단어 변환 자바 풀이 (1) | 2024.11.20 |
프로그래머스 43163 단어 변환 파이썬 풀이 (1) | 2024.11.14 |
프로그래머스 43164 여행경로 파이썬 풀이 (0) | 2024.11.14 |