Algorithm/BOJ
[백준] 16681번 등산
면빈이
2019. 11. 28. 23:52
[적용한 알고리즘]
다익스트라
[아이디어]
목표지로 갈 때, 어차피 추가되는 성취감은 각 노드를 어떤 식으로 방문했든 h * E 로 일정하다.
그러므로, 가치가 최대가 되려면, 잃는 체력을 최소로 만들면 된다.
[생각의 흐름 / 절차]
문제의 주인공이 하는 짓을 2개의 파트로 나눌 수 있다.
1. 목표지로 간다.
2. 고려대(부럽..)으로 간다.
따라서, 2개의 절차로 나누어서 생각해볼 수 있다.
1. 1번 노드에서 X (2<= X <= N - 1) 번 노드로 가는 최소거리를 저장하는 dist 배열
2. N번 노드에서 X (2<= X <= N - 1)번 노드로 가는 최소거리를 저장하는 dist2 배열
을 다익스트라로 구해준 뒤, E * height[X] - (dist[X] + dist2[X]) * D 의 최댓값을 찾아주면 된다.
[교훈]
문항이 요구하는 조건을 정확하게 구현하는게 쉽지는 않았다.
문제를 천천히 읽어보면서 다익스트라라는 감을 잡아야겠다.
그리고, 로직은 맞는거 같은데 계속 틀렸길래 자료형을 다 long long 으로 뜯어 고치고, 별 짓을 다했다.
코드가 복잡해 가독성이 많이 떨어지니 다시 깔끔하게 코드를 쓰고 업데이트를 해야겠다. (업데이트 완료)
<코드>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#define INF 1000000000000
const int MAX_N = 100001;
using namespace std;
typedef pair<int, long long> P;
typedef long long int lld;
int N, M, D, E; //D: 체력 소모량, E: 성취감
int height[MAX_N];
vector<P> adj[MAX_N];
void dijkstra(int start_node, lld dist[]){
priority_queue<P, vector<P>, greater<P>> PQ;
bool visited[MAX_N] = { 0 };
fill(dist, dist + N + 1, INF);
dist[start_node] = 0;
PQ.push(P(0, start_node));
while (!PQ.empty()){
int cur;
do {
cur = PQ.top().second;
PQ.pop();
} while (!PQ.empty() && visited[cur]);
if (visited[cur]) break;
visited[cur] = true;
for (auto &p : adj[cur]){
int nxt_node = p.first;
int nxt_cost = p.second;
if (height[nxt_node] > height[cur]){
if (dist[nxt_node] > dist[cur] + nxt_cost){
dist[nxt_node] = dist[cur] + nxt_cost;
PQ.push(P(dist[nxt_node], nxt_node));
}
}
}
}
}
int main(){
scanf("%d %d %d %d", &N, &M, &D, &E);
for (int i = 1; i <= N; i++){
scanf("%d", &height[i]);
}
for (int i = 1; i <= M; i++){
int from, to, cost;
scanf("%d %d %d", &from, &to, &cost);
adj[from].push_back(P(to, cost));
adj[to].push_back(P(from, cost));
}
lld dist1[MAX_N];
lld dist2[MAX_N];
dijkstra(1, dist1);
dijkstra(N, dist2);
lld ans = -INF;
for (int i = 2; i <= N - 1; i++){
if (dist1[i] == INF || dist2[i] == INF) continue;
lld res = height[i] * E - (dist1[i] + dist2[i]) * D;
ans = max(ans, res);
}
if (ans == -INF) printf("Impossible\n");
else printf("%lld", ans);
return 0;
}