안녕하세요! 이번 포스트에서는 최소 비용 구하기라는 주제로 C++ 알고리즘 문제를 다뤄보겠습니다. 이 문제는 여러 상황에서 최적의 해결책을 찾는 데 유용하게 쓰이는 알고리즘 개념들을 살펴보는 좋은 기회가 될 것입니다. 이 글을 통해 우리는 문제분석, 알고리즘 선택, 코드 구현, 테스트, 그리고 최적화 방법까지 상세히 알아보겠습니다.
문제 설명
우리에게는 여러 개의 도시와 이들 사이의 도로가 있습니다. 각 도로는 특정 비용을 가지고 있습니다. 주어진 여러 도시들 간에 이동할 때, 우리의 목표는 시작 도시에서 목표 도시까지의 최소 이동 비용을 구하는 것입니다. 이를 다익스트라 알고리즘을 통해 해결할 수 있습니다.
문제 정의
다음은 문제의 수학적 정의입니다:
- 주어진 도시의 수
n
(1 이상 10,000 이하) - 경로의 개수
m
(1 이상 100,000 이하) - 각 경로는
u
,v
,cost
의 형태로 입력됩니다. 이는 도시u
에서 도시v
로 가는 비용이cost
라는 것을 의미합니다. - 시작 도시
start
와 목표 도시end
가 주어집니다.
입력
n m
u1 v1 cost1
u2 v2 cost2
...
um vm costm
start end
출력
목표 도시까지 가는 최소 비용을 출력합니다. 만약 도착할 수 없다면 -1
을 출력합니다.
알고리즘 선택
이 문제는 가중치 그래프에서 최단 경로를 찾는 문제로, 대표적인 알고리즘인 다익스트라 알고리즘을 사용하여 해결할 수 있습니다. 다익스트라 알고리즘은 O((n + m) log n)
의 시간 복잡도를 가지므로, 최대 입력 조건에서도 효율적으로 동작합니다.
다익스트라 알고리즘 개요
다익스트라 알고리즘의 기본 아이디어는 다음과 같습니다:
- 시작 노드를 선택하고, 이 노드까지의 거리를 0으로 초기화합니다.
- 나머지 모든 노드까지의 거리를 무한대로 초기화합니다.
- 현재 노드와 인접한 노드로의 거리를 계산하여, 더 짧은 거리가 발견되면 거리를 업데이트합니다.
- 모든 노드가 방문될 때까지 과정을 반복합니다.
문제 해결 과정
1단계: 문제 분석
주어진 입력을 통해 그래프를 구성하고, 각 도시에 대한 비용 정보를 저장할 데이터 구조가 필요합니다. 우리는 인접 리스트를 사용할 것입니다.
2단계: 코드 구현
#include <iostream>
#include <vector>
#include <queue>
#include <utility>
#include <limits>
using namespace std;
const int INF = numeric_limits<int>::max();
vector<pair<int, int>> graph[10001];
void dijkstra(int start, int n) {
vector<int> cost(n + 1, INF);
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
cost[start] = 0;
pq.push(make_pair(0, start));
while (!pq.empty()) {
int currentCost = pq.top().first;
int currentNode = pq.top().second;
pq.pop();
if (currentCost > cost[currentNode]) continue;
for (auto &edge : graph[currentNode]) {
int nextNode = edge.first;
int nextCost = edge.second;
if (cost[currentNode] + nextCost < cost[nextNode]) {
cost[nextNode] = cost[currentNode] + nextCost;
pq.push(make_pair(cost[nextNode], nextNode));
}
}
}
for (int i = 1; i <= n; ++i) {
if (cost[i] == INF) {
cout << -1 << endl; // 도달할 수 없는 경우
} else {
cout << cost[i] << endl;
}
}
}
int main() {
int n, m;
cin >> n >> m;
for (int i = 0; i < m; ++i) {
int u, v, cost;
cin >> u >> v >> cost;
graph[u].push_back(make_pair(v, cost));
graph[v].push_back(make_pair(u, cost)); // 양방향 도로 가정
}
int start, end;
cin >> start >> end;
dijkstra(start, n);
return 0;
}
3단계: 코드 테스트
위 코드를 통해 입력을 테스트합니다. 예를 들어, 다음 입력을 통해 테스트를 해 볼 수 있습니다:
5 6
1 2 1
1 3 4
2 3 2
2 4 5
3 4 1
4 5 3
1 5
위 입력은 도시 5개와 6개의 도로가 있는 경우로, 시작 도시가 1번, 목표 도시가 5번입니다. 이 경우 알고리즘은 최소 비용으로 1번 도시에서 5번 도시까지 가는 방법을 출력해야 합니다.
4단계: 최적화
다익스트라 알고리즘은 일반적으로 Priority Queue를 사용하여 구현하지만, 제한이 있는 경우에는 Fibonacci Heap 등을 사용할 수 있습니다. 그러나 이 글에서는 일반적인 Priority Queue를 사용하여 간단하고 효율적인 구현을 보여주었습니다.
결론
이번 강좌에서는 C++로 최소 비용 구하기 문제를 해결하는 방법을 살펴보았습니다. 다익스트라 알고리즘의 원리를 이해하고 이를 실제 문제에 어떻게 적용하는지 다뤘습니다. 이는 코딩 테스트를 대비하는 데 도움이 될 것입니다.
계속해서 더 많은 알고리즘 문제를 해결하는 방법을 배우고 연습하시길 바랍니다. 감사합니다!