개인사
[G4] 백준 20007번 떡 돌리기 C++ 다익스트라, 정렬 본문
728x90

리뷰

https://www.acmicpc.net/problem/20007
처음엔 이해가 잘 가지 않았는데, 다익스트라로 최단거리 계산 후 정렬을 통해 그리디가 추가된 문제인 것 같다.
전역 변수
- N : 배열의 최대 크기를 정의할 상수 변수
- n : 노드의 개수를 저장할 변수
- m : 간선의 개수를 저장할 변수
- x : 하루에 갈 수 있는 거리의 최대값을 저장할 변수
- y : 시작 노드의 번호를 저장할 변수
- Edge : 간선 정보를 정의할 구조체
- edges : 간선 정보를 저장할 Edge타입 벡터 배열 인접리스트
- Pos : 현재 위치 정보를 정의할 구조체, 누적 가중치를 기준으로 오름차순 정렬한다.
함수
1. dijkstra
vector<int> dijkstra() {
priority_queue<Pos> pq;
pq.push({ y, 0 });
vector<int> dist(n, 2e9);
dist[y] = 0;
while (!pq.empty()) {
Pos pos = pq.top(); pq.pop();
int cn = pos.cn, cv = pos.cv;
if (dist[cn] < cv) continue;
for (const Edge& edge : edges[cn]) {
int nn = edge.nn, nv = cv + edge.nv;
if (dist[nn] > nv) {
dist[nn] = nv;
pq.push({ nn, nv });
}
}
}
return dist;
}
다익스트라를 통해 출발점으로 부터 모든 노드까지의 최단 거리를 구하고 반환하기 위한 함수
문제풀이
- n, m, x, y값을 입력 받고, m개의 간선 정보를 입력 받아 edges배열을 초기화한다.
- 정수형 벡터 dist를 dijkstra함수를 호출하여 반환받은 시작노드으로 부터 모든 노드까지의 최단 거리를 저장한다.
- sort함수를 통해 dist벡터를 오름차순으로 정렬한다.
- 변수 a, s를 0으로 초기화하고, 모든 노드를 순회하는 for문을 개행한다.
- 변수 d에 현재 노드까지의 거리의 2배를 저장한다.
- d가 x보다 크다면 해당 노드는 방문할 수 없으므로 -1을 출력하고 조기 종료한다.
- s+d가 x보다 크다면 a를 증가시키고, s를 d로 저장한다.
- s+d가 x보다 작거나 같다면 s에 d를 추가한다.
- 모든 탐색을 마친 후 마지막으로 s가 0이 아닐경우 a를 증가시킨다.
- a에 저장된 값을 출력한다.
트러블 슈팅
- 다익스트라 내부에서 다음 간선의 가중치를 저장할때 nv = cn + edge.nv; 로 처리하여 WA를 받았다.
- 간선의 가중치를 저장할때 nv = cv + edge.nv;로 올바르게 처리하여 제출하니 AC를 받았다.
참고 사항
- 값의 범위는 (2 ≤ N ≤ 1,000, 1 ≤ M ≤ 100,000, 1 ≤ X ≤ 10,000,000, 0 ≤ Y < N)로 int자료형으로 처리 가능하다.
- 잠은 꼭 본인 집에서 자야 한다. 떡은 한번에 하나씩만 들고 갈 수 있다.
- 즉, 매번 자신의 집을 들려야 하므로 노드 방문 가중치는 최단 거리의 2배로 보는 것이 맞다.
정답 코드
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 1e3;
int n, m, x, y;
struct Edge {
int nn, nv;
};
vector<Edge> edges[N];
struct Pos {
int cn, cv;
bool operator<(const Pos& other) const {
return cv > other.cv;
}
};
vector<int> dijkstra() {
priority_queue<Pos> pq;
pq.push({ y, 0 });
vector<int> dist(n, 2e9);
dist[y] = 0;
while (!pq.empty()) {
Pos pos = pq.top(); pq.pop();
int cn = pos.cn, cv = pos.cv;
if (dist[cn] < cv) continue;
for (const Edge& edge : edges[cn]) {
int nn = edge.nn, nv = cv + edge.nv;
if (dist[nn] > nv) {
dist[nn] = nv;
pq.push({ nn, nv });
}
}
}
return dist;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m >> x >> y;
while (m--) {
int f, t, v; cin >> f >> t >> v;
edges[f].push_back({ t, v });
edges[t].push_back({ f, v });
}
vector<int> dist = dijkstra();
sort(dist.begin(), dist.end());
int a = 0, s = 0;
for (int i = 0; i < n; ++i) {
int d = dist[i] * 2;
if (d > x) {
cout << -1;
return 0;
}
if (s + d > x) {
++a;
s = d;
}
else s += d;
//cout << a << " " << s << " " << d << "\n";
}
if (s) ++a;
cout << a;
}728x90
'알고리즘 공부 > C++' 카테고리의 다른 글
| [P3] 백준 17407번 괄호 문자열과 쿼리 C++ 세그먼트 트리 (0) | 2025.11.12 |
|---|---|
| [P5] 백준 27897번 특별한 화재 경보 C++ 세그먼트 트리 (0) | 2025.11.11 |
| [G4] 백준 13422번 도둑 C++ 슬라이딩 윈도우 (1) | 2025.11.09 |
| [G4] 백준 6137번 문자열 생성 C++ 덱, 문자열, 투 포인터 (0) | 2025.11.07 |
| [G3] 백준 17951번 흩날리는 시험지 속에서 내 평점이 느껴진거야 C++ 이분 탐색, 매개 변수 탐색 (0) | 2025.11.06 |
