티스토리 뷰
https://www.acmicpc.net/problem/16118
16118번: 달빛 여우
첫 줄에 나무 그루터기의 개수와 오솔길의 개수를 의미하는 정수 N, M(2 ≤ N ≤ 4,000, 1 ≤ M ≤ 100,000)이 주어진다. 두 번째 줄부터 M개의 줄에 걸쳐 각 줄에 세 개의 정수 a, b, d(1 ≤ a, b ≤ N, a ≠ b
www.acmicpc.net
문제
관악산 기슭에는 보름달을 기다리는 달빛 여우가 한 마리 살고 있다. 달빛 여우가 보름달의 달빛을 받으면 아름다운 구미호로 변신할 수 있다. 하지만 보름달을 기다리는 건 달빛 여우뿐만이 아니다. 달빛을 받아서 멋진 늑대인간이 되고 싶어 하는 달빛 늑대도 한 마리 살고 있다.
관악산에는 1번부터 N번까지의 번호가 붙은 N개의 나무 그루터기가 있고, 그루터기들 사이에는 M개의 오솔길이 나 있다. 오솔길은 어떤 방향으로든 지나갈 수 있으며, 어떤 두 그루터기 사이에 두 개 이상의 오솔길이 나 있는 경우는 없다. 달빛 여우와 달빛 늑대는 1번 나무 그루터기에서 살고 있다.
보름달이 뜨면 나무 그루터기들 중 하나가 달빛을 받아 밝게 빛나게 된다. 그러면 달빛 여우와 달빛 늑대는 먼저 달빛을 독차지하기 위해 최대한 빨리 오솔길을 따라서 그 그루터기로 달려가야 한다. 이때 달빛 여우는 늘 일정한 속도로 달려가는 반면, 달빛 늑대는 달빛 여우보다 더 빠르게 달릴 수 있지만 체력이 부족하기 때문에 다른 전략을 사용한다. 달빛 늑대는 출발할 때 오솔길 하나를 달빛 여우의 두 배의 속도로 달려가고, 그 뒤로는 오솔길 하나를 달빛 여우의 절반의 속도로 걸어가며 체력을 회복하고 나서 다음 오솔길을 다시 달빛 여우의 두 배의 속도로 달려가는 것을 반복한다. 달빛 여우와 달빛 늑대는 각자 가장 빠르게 달빛이 비치는 그루터기까지 다다를 수 있는 경로로 이동한다. 따라서 둘의 이동 경로가 서로 다를 수도 있다.
출제자는 관악산의 모든 동물을 사랑하지만, 이번에는 달빛 여우를 조금 더 사랑해 주기로 했다. 그래서 달빛 여우가 달빛 늑대보다 먼저 도착할 수 있는 그루터기에 달빛을 비춰 주려고 한다. 이런 그루터기가 몇 개나 있는지 알아보자.
유형 : 다익스트라
접근 방식
- 시간이 굉장이 엄격한 문제라서 다익스트라에서의 모든 최적화를 다 해야 한다.
- 하지만 자바로 문제를 푸는 경우 그것을 넘어서 코드를 줄이는 최적화 또한 필요하다.
- 문제 해결 방식은 간단한데 다익스트라를 2번 수행하면 된다.
- 달빛 여우가 움직이는 다익스트라
- 달빛 늑대가 움직이는 다익스트라
- 늑대의 경우 거리 배열을 2차원으로 선정
- [i][0]의 경우 해당 지점에서 c / 2 로 움직여야 할 때
- [i][1]의 경우 해당 지점에서 c * 2 로 움직여야 할 때
- 늑대의 경우 거리 배열을 2차원으로 선정
- 그리고 입력을 받을 때 거리를 *2로 저장해야 한다. ( 홀수 나누기에 대한 예시가 없기 때문에 !!!! )
전체 코드
import java.util.*;
import java.io.*;
public class Main {
static long[] foxDis;
static long[][] wolfDis;
static ArrayList<Node>[] graph;
static int n,m;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine()," ");
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
graph = new ArrayList[n+1];
foxDis = new long[n+1];
wolfDis = new long[n+1][2];
for(int i = 1 ; i <= n ; i++){
graph[i] = new ArrayList<>();
}
for(int i = 1 ; i <= m ; i++){
st = new StringTokenizer(br.readLine()," ");
int v1 = Integer.parseInt(st.nextToken());
int v2 = Integer.parseInt(st.nextToken());
int c = Integer.parseInt(st.nextToken()) * 2;
graph[v1].add(new Node(v2,c));
graph[v2].add(new Node(v1,c));
}
foxMove();
wolfMove();
int count = 0;
for(int i = 2 ; i <= n ; i++){
if(foxDis[i] < Math.min(wolfDis[i][0],wolfDis[i][1])){
count++;
}
}
System.out.println(count);
br.close();
}
static void wolfMove(){
PriorityQueue<Point> pq = new PriorityQueue<>(
(x,y) -> Long.compare(x.c,y.c)
);
for(int i = 2 ; i <= n ; i++){
for(int j = 0 ; j <= 1 ; j++){
wolfDis[i][j] = Long.MAX_VALUE;
}
}
wolfDis[1][1] = Long.MAX_VALUE;
pq.add(new Point(1,0,0));
while(!pq.isEmpty()){
Point cur = pq.poll();
if(wolfDis[cur.v][cur.type] < cur.c)
continue;
for(Node next : graph[cur.v]){
if(cur.type == 0){
long nextDis = cur.c + next.c / 2;
if(wolfDis[next.v][1] <= nextDis){
continue;
}
wolfDis[next.v][1] = nextDis;
pq.add(new Point(next.v,nextDis,1));
continue;
}else{
long nextDis = cur.c + (2* next.c);
if(wolfDis[next.v][0] <= nextDis){
continue;
}
wolfDis[next.v][0] = nextDis;
pq.add(new Point(next.v,nextDis,0));
continue;
}
}
}
}
static void foxMove(){
PriorityQueue<Node> pq = new PriorityQueue<>(
(x,y) -> Long.compare(x.c,y.c)
);
for(int i = 1 ; i <= n ; i++){
foxDis[i] = Long.MAX_VALUE;
}
foxDis[1] = 0;
pq.add(new Node(1,0));
while(!pq.isEmpty()){
Node cur = pq.poll();
if(foxDis[cur.v] < cur.c)
continue;
for(Node next : graph[cur.v]){
if(foxDis[next.v] <= cur.c + next.c){
continue;
}
foxDis[next.v] = cur.c + next.c;
pq.add(new Node(next.v,foxDis[next.v]));
}
}
}
static class Node{
int v;
long c;
Node(int v,long c){
this.v = v;
this.c = c;
}
}
static class Point{
int v;
long c;
int type;
Point(int v,long c,int type){
this.v = v;
this.c = c;
this.type = type;
}
}
}
'알고리즘 > 백준' 카테고리의 다른 글
백준 10776 (제국) - java (0) | 2024.04.24 |
---|---|
백준 24391 (귀찮은 해강이) - java (0) | 2024.04.23 |
백준 2632 (피자판매) - java (0) | 2024.04.15 |
백준 17143 (낚시왕) - java (0) | 2024.04.02 |
백준 18224 (미로에 갇힌 건우) - java (0) | 2024.03.31 |
- Total
- Today
- Yesterday
- 백준 #28140 #빨강~ 빨강~ 파랑! 파랑! 달콤한 솜사탕! #java #자바
- 백준 #3980 #선발 명단
- 백준 #18405 #경쟁적 전염
- 백준 #13549 #숨바꼭질3
- 17218
- 백준 #다리 만들기 #2146
- 백준
- 백준 #인구 이동 #16234
- 백준 #2636 #치즈
- 백준 #1727 #커플 만들기 #자바 #java
- 백준 #25603 #짱해커 이동식 #java #자바
- 백준 #1987 #알파벳 #자바 #java
- 백준 #1325 #효율적인 해킹
- 백준 #1584 #게임 #java #자바
- 백준 #4963 #섬의 개수
- 백준 #15686 #치킨 배달
- 백준 #1759 #암호 만들기
- 백준 #17940 #주식 #자바 #java
- 백준 #25195 #yes or yes #java #자바
- 백준 #치즈 #2638
- 백준 #12014 #주식 #자바 #java
- 백준 #5721 #사탕 줍기 대회 #java #자바
- 백준 #16973 #직사각형 탈출
- 백준 #
- 백준 #2580 #스도쿠
- 자바
- 자바 #JAVA
- 17394
- 백준 #14863 #서울에서 경산까지 #java #자바
- Java
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |