일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 에라토스테네스의 체
- DP
- 구현
- 수학
- 세그먼트트리
- boj
- DisjointSet
- 비트마스크
- 플로이드와샬
- MST
- 정렬
- 이진탐색
- 좌표압축
- BFS
- 누적합
- 다익스트라
- 크루스칼
- LazyPropagation
- 삼분탐색
- lis
- 브루트포스
- 펜윅트리
- 위상정렬
- 투포인터
- 이분탐색
- 이분매칭
- dfs
- lca
- 백준
- 그리디
Archives
- Today
- Total
lastknight00
[백준]주유소(13308) 본문
문제 링크 : [백준]주유소(13308)
문제 설명
N개의 도시가 있고, 각 도시에는 주유소가 있고 각 주유소마다 기름값이 주어집니다.
도시간 도로의 거리가 주어졌을 때, 1번 도시에서 출발하여, N번 도시에 도착하기 위한 최소 기름값을 구하세요.
입력
N(도시 갯수, 1 <= N <= 2,500)
M(도로의 갯수, 1 <= M <= 4,000)
Oi(각 도시의 기름값, 1 <= Oi <= 2,500)
Si Ei Di(출발 도시, 도착 도시, 도시간 거리, 1 <= Di <= 2,500)
4 4
5 2 4 1
3 1 3
1 2 2
4 3 4
2 4 15
출력
28
카테고리
#다익스트라 #DP
시간 복잡도 상한
O(N * M * logM)
해결 방법
- 얼핏 보면 단순 다익스트라처럼 보입니다.
- 하지만 비용을 구하는 방식이 단순 엣지의 비용이 아닌, 엣지 비용 * 기름값으로 비용을 구하는 방식이 다릅니다.
- 정확하게 비용을 구하는 방식은, [현재까지 비용 + 현재까지 방문한 도시들의 기름값 중 최소값 * 다음 도시까지의 거리]가 됩니다.
- 이 내용을 우선순위 큐에 넣으면 될 것 같지만, 이렇게 하게되면, 예제에서 처럼 1번에서 2번을 방문하면서 최소 기름값이 변경되어 다시 돌아오는 경우를 처리할 수 없습니다.
4-1. 이미 1번 노드의 최소비용은 0으로 책정되었기 때문에, 일반적인 다익스트라에서는 다음에 더 큰 비용이 오기 때문에 무시됩니다. - 그렇다고 이미 책정된 최소비용을 무시하고 계속 간선 정보들을 넣다보면 TLE가 발생합니다.
- 현재 노드에 방문하는 최소 비용을 노드 번호와 지금까지의 최소기름값을 가지고 관리하게 합니다.
- 따라서 이미 방문한 노드라도 더 작은 최소 기름값으로 왔다면 정보를 추가하여 다익스트라를 진행합니다.
- 그 이후에는 N번 노드가 나올 때까지 다익스트라를 돌리면 됩니다.
시간복잡도
O(N * M * logM)
코드
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#define sf second.first
#define ss second.second
#define M 999999999999
using namespace std;
typedef pair<int,int>P;
typedef long long L;
int n,m,o[2501],i,j,a,b,c;
vector<P>v[2501];
priority_queue<pair<L,P>,vector<pair<L,P>>,greater<pair<L,P>>>q;
bool d[2501][2501];
int main(){
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)scanf("%d",o+i);
while(m--){
scanf("%d%d%d",&a,&b,&c);
v[a].push_back({b,c});
v[b].push_back({a,c});
}
q.push({0,{1,o[1]}});
while(!q.empty()){
pair<L,P>x=q.top();q.pop();
if(d[x.sf][x.ss])continue;
if(x.sf==n){
printf("%lld",x.first);
break;
}
d[x.sf][x.ss]=x.first;
for(P y:v[x.sf]){
if(d[y.first][min(x.ss,o[y.first])])continue;
q.push({x.first+x.ss*y.second,{y.first,min(x.ss,o[y.first])}});
}
}
}
'PS' 카테고리의 다른 글
[백준]일요일 아침의 데이트(1445) (0) | 2020.07.18 |
---|---|
[백준]지름길(1446) (0) | 2020.07.18 |
[백준]강의실 배정(11000) (0) | 2020.07.18 |
[백준]비밀 모임(13424) (0) | 2020.07.18 |
[백준]숫자구슬(2613) (0) | 2020.07.15 |
Comments