코테/백준

[백준/JAVA] 1219번: 오민식의 고민

imname1am 2023. 5. 2. 23:57
반응형

🔺 문제

 

1219번: 오민식의 고민

첫째 줄에 도착 도시에 도착할 때, 가지고 있는 돈의 액수의 최댓값을 출력한다. 만약 오민식이 도착 도시에 도착하는 것이 불가능할 때는 "gg"를 출력한다. 그리고, 오민식이 도착 도시에 도착

www.acmicpc.net

민식이냐?

 

🔺 코드

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import java.util.*;
import java.io.*;
 
public class Main {
    static int N, S, E, M;
    static Edge[] edges; // 에지 리스트
    static long[] dist;  // 거리 배열
    static long[] cityMoney; // 가격 배열
    
    public static void main(String[] args) throws IOException {
        BufferedReader  br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine()," ");
        
        N = Integer.parseInt(st.nextToken());   // 도시 수
        S = Integer.parseInt(st.nextToken());   // 시작 도시
        E = Integer.parseInt(st.nextToken());   // 도착 도시
        M = Integer.parseInt(st.nextToken());   // 교통수단 개수
        
        // 최단 거리 배열 초기화
        dist = new long[N];
        Arrays.fill(dist, Long.MIN_VALUE);
        dist[S] = 0;
        
        // 에지 리스트 채우기
        edges = new Edge[M];
        for(int i = 0 ; i < M ; i++) {
            st = new StringTokenizer(br.readLine()," ");
            int start = Integer.parseInt(st.nextToken());
            int end   = Integer.parseInt(st.nextToken());
            int price = Integer.parseInt(st.nextToken());
            
            edges[i] = new Edge(start, end, price);
        }
        
        // 가격 배열
        cityMoney = new long[N];
        st = new StringTokenizer(br.readLine(), " ");
        for(int i = 0 ; i < N ; i++) {
            cityMoney[i] = Long.parseLong(st.nextToken());
        }
        
        System.out.println(bellmanFord());
    }
    
    // 변형된 벨만-포드
    public static String bellmanFord() {
        dist[S] = cityMoney[S];
        
        for(int i = 0 ; i <= N + 100 ; i++) {  // 양수 사이클 전파되도록 충분히 큰 수로 반복
            for(int j = 0 ; j < M ; j++) {
                int start = edges[j].start;
                int end   = edges[j].end;
                int price = edges[j].price;                
                
                // 출발 노드가 방문하지 않은 노드면 스킵
                if(dist[start] == Long.MIN_VALUE) continue;
                // 출발 노드가 양수 사이클에 연결된 노드라면, 종료 노드도 연결 노드로 업데이트
                else if(dist[start] == Long.MAX_VALUE)
                    dist[end] = Long.MAX_VALUE;
                // 돈 더 벌 수 있는 새 경로 발견 시, 업데이트
                else if(dist[end] < dist[start] + cityMoney[end] - price) {
                    dist[end] = dist[start] + cityMoney[end] - price;
                    
                    if(i >= N - 1) dist[end] = Long.MAX_VALUE;  // N-1 반복 이후 업데이트 되는 종료 노드, 양수 사이클 연결 노드로 변경
                }
            }
        }
        
        // 도착 도시의 값에 따른 결과 출력
        if(dist[E] == Long.MIN_VALUE)       return "gg";    // 도착 불가
        else if(dist[E] == Long.MAX_VALUE)  return "Gee";   // 양수 사이클이 연결돼 무한대 돈을 벌 수 있음
        else                                return Long.toString(dist[E]);
    }
}
 
// 에지 클래스
class Edge {
    int start, end, price;
    
    Edge(int start, int end, int price) {
        this.start = start;
        this.end = end;
        this.price = price;
    }
}
cs
✅ 해결 아이디어
✔ 벨만-포드 알고리즘 변형!!!
- 업데이트 방식 : 돈 더 벌 수 있는 새 경로 발견 시, 업데이트
- 양수 사이클 탐색 ; N의 최대치만큼 반복

 

💥 유의사항

⇨ 시간 복잡도 :  O(MN)

 


🔺 다른 풀이들

- 인접 리스트 사용

 

[백준] 1219 : 오민식의 고민 - JAVA

🙋 벨만-포드 알고리즘 사용! 틀렸습니다를 받았다.에지를 체크할 때 시작 노드가 양의 사이클에 속하면, 도착 노드도 양의 사이클에 속하도록 해야한다. (무수히 많이 반복되면, 양의사이클이

velog.io

 

 

- 설명이 굿

 

BOJ#1219 오민식의 고민

BOJ#1219 오민식의 고민 * 문제https://www.acmicpc.net/problem/1219 * 풀이벨만-포드 최단거리 문제입니다. 간선 cost는 음수이고, 각 노드마다 추가로 돈을 벌 수 있습니다.원하는 것은 S(시작점)에서 D(도착

stack07142.tistory.com


💬 느낀 점

응용은 또 어렵군...하핫

 

 

1회독 2회독 3회독 4회독 5회독
V        

(참고)

✔ DO it 알고리즘 코딩테스트 자바편

 

반응형