728x90
난이도 : 골드3
풀이일 : 2401173
https://www.acmicpc.net/problem/11779
11779번: 최소비용 구하기 2
첫째 줄에 도시의 개수 n(1≤n≤1,000)이 주어지고 둘째 줄에는 버스의 개수 m(1≤m≤100,000)이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스
www.acmicpc.net
링크로 이동하기 귀찮은 분들을 위한 문제 캡쳐
1차 시도 오답
import sys, heapq
def djikstra(num):
visited[num] = [0, f'{num}']
queue = []
heapq.heappush(queue, [visited[num], num])
while queue:
load, now = heapq.heappop(queue)
if load[0] <= visited[now][0]:
for add, next in bus[now]:
if visited[next][0] > load[0] + add:
visited[next][0] = load[0] + add
visited[next][1] = load[1] + f'{next}'
heapq.heappush(queue, [visited[next], next])
return
n = int(sys.stdin.readline())
m = int(sys.stdin.readline())
bus = [[] for _ in range(n + 1)]
visited = [[n * 100000, ""] for _ in range(n+1)]
for _ in range(m):
s, e, v = list(map(int, sys.stdin.readline().split()))
bus[s].append([v, e])
start, end = list(map(int, sys.stdin.readline().split()))
djikstra(start)
print(visited[end][0])
print(len(visited[end][1]))
for i in visited[end][1]:
print(i, end=" ")
코드 구성
- 다익스트라 풀이
- bus의 출발도시 번호에 도착 도시까지의 비용과 도착 도시의 정보를 리스트로 추가
- visited 배열을 2차원으로 구성하여, 비용과 지나온 도시 정보를 함께 저장하도록 설정
- 다익스트라 방식으로 출발도시부터 도착도시까지의 최소 비용, 지나온 도시를 탐색
틀린 이유
- 문자열로 지나온 도시를 저장해두었기 때문에, 두 자리수 이상의 숫자 도시에서 출력 시 문제 발생
- ex) 10 번 도시를 거쳐왔을 경우, 1과 0 도시를 지나온 것처럼 출력
2차 시도 오답 - 시간초과
import sys, heapq
def djikstra(num):
visited[num] = [0, [num]]
queue = []
heapq.heappush(queue, [visited[num], num])
while queue:
load, now = heapq.heappop(queue)
if load[0] <= visited[now][0]:
for add, next in bus[now]:
if visited[next][0] > load[0] + add:
visited[next][0] = load[0] + add
visited[next][1] = load[1] + [next]
heapq.heappush(queue, [visited[next], next])
return
n = int(sys.stdin.readline())
m = int(sys.stdin.readline())
bus = [[] for _ in range(n + 1)]
visited = [[int(1e9), []] for _ in range(n+1)]
for _ in range(m):
s, e, v = list(map(int, sys.stdin.readline().split()))
bus[s].append([v, e])
start, end = list(map(int, sys.stdin.readline().split()))
djikstra(start)
print(visited[end][0])
print(len(visited[end][1]))
for i in visited[end][1]:
print(i, end=" ")
코드 변화
- visited의 최댓값을 1e9로 변환
- 특정 도시의 visited 내부에서 지나온 도시 저장 방식을 문자열에서 리스트로 변환
틀린 이유
- 다익스트라 내부에서 append 방식을 사용하였기 때문에, 매 번 리스트를 복사하는 과정에서 시간초과 발생
3차 시도 정답
import sys, heapq
def djikstra(num):
visited[num] = 0
queue = []
heapq.heappush(queue, [0, num])
while queue:
cost, now = heapq.heappop(queue)
if cost <= visited[now]:
for add, next in bus[now]:
if visited[next] > cost + add:
visited[next] = cost + add
previous[next] = now
heapq.heappush(queue, [cost + add, next])
return
n = int(sys.stdin.readline())
m = int(sys.stdin.readline())
bus = [[] for _ in range(n + 1)]
visited = [int(1e9) for _ in range(n+1)]
previous = [-1 for _ in range(n + 1)]
for _ in range(m):
s, e, v = list(map(int, sys.stdin.readline().split()))
bus[s].append([v, e])
start, end = list(map(int, sys.stdin.readline().split()))
djikstra(start)
result = [end]
print(visited[end])
while end != start:
end = previous[end]
result.append(end)
print(len(result))
for i in result[::-1]:
print(i, end=" ")
코드 변화
- visited 배열을 1차원 배열로 수정
- previous 배열을 생성하여 초기값을 -1로 설정
- 새 도시 방문 시, 이전 도시 정보를 previous 배열에 저장
- 출발 도시에서 도착 도시까지의 최소 비용 구한 후, 반복문을 통해 방문 도시 정보를 탐색
- 구한 방문 도시들을 뒤에서부터 출력
느낀점
- 어제, 그저게 다익스트라 문제 풀어서 날로 먹으려고 골랐는데 난이도를 보고 고를걸 그랬다.
- 문자열 코드에서 문제를 찾는데에도, 리스트로 수정 후 문제를 찾는 데에도 생각보다 시간을 너무너무 오래썼다.
- 매일 파이썬 문제랑 자바 문제를 하나씩 풀고 싶으니까 조금씩만 더 빨리 풀기 시작해야지
'알고리즘 > 🥇 골드' 카테고리의 다른 글
백준 1504 특정한 최단 거리 파이썬 풀이, 반례 (0) | 2024.01.19 |
---|---|
백준 1967 트리의 지름 파이썬 풀이 (0) | 2024.01.18 |
백준 1753 최단경로 파이썬 풀이 (0) | 2024.01.16 |
백준 1916 최소비용 구하기 파이썬 풀이, 시간초과, heapq vs deque (0) | 2024.01.15 |
백준 1717 집합의 표현 파이썬 풀이 (1) | 2024.01.14 |