IT/알고리즘

백준 1238 파티

어센트 2020. 4. 7. 21:02

https://www.acmicpc.net/problem/1238

 

1238번: 파티

문제 N개의 숫자로 구분된 각각의 마을에 한 명의 학생이 살고 있다. 어느 날 이 N명의 학생이 X (1 ≤ X ≤ N)번 마을에 모여서 파티를 벌이기로 했다. 이 마을 사이에는 총 M개의 단방향 도로들이 있고 i번째 길을 지나는데 Ti(1 ≤ Ti ≤ 100)의 시간을 소비한다. 각각의 학생들은 파티에 참석하기 위해 걸어가서 다시 그들의 마을로 돌아와야 한다. 하지만 이 학생들은 워낙 게을러서 최단 시간에 오고 가기를 원한다. 이 도로들은 단방향이기 때

www.acmicpc.net

배운점

단방향 그래프에서 다익스트라 알고리즘을 활용하여 문제를 해결하는 문제였다.

다익스트라 알고리즘이 어떤 방식으로 구현되는지에 대해 알고 실제로 코드를 작성하여 문제를 풀어본 건 3학년 1학기 알고리즘 시간이었으니... 거의 1년이 다되가는 것 같다.

덕분에 다익스트라를 구현하는데 많은 시간이 걸렸다. 

  • 방문했는 지를 확인하는 배열vis 과 시작노드(start)부터 그 노드까지의 거리를 저장할 배열 dArr을 만들었다.
  • dArr을 최대로 초기화 vis를 false로 전부초기화
  • 시작노드와 인접한 노드 거리 계산 dArr 수정
  • 방문하지 않고 인접한 노드를 찾으며 dArr의 값이 가장 적은 노드(index)로 방문
  • 이 가장 적은 노드(index)와 인접하고 방문하지않은 노드를 찾고 현재까지 dArr[j]와 이 index를 거쳤을 경우(Arr[index][j]+dArr[index])를 비교하여 더 짧은 값으로 수정 
  • 모든 노드를 확인하기위해 위 모든 과정 n-1번 수행 ==방문하지않은 노드가 있을 때 까지 수행

 

 

 

 

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
package 번호별;
 
import java.io.*;
import java.util.*;
 
public class Pro1238 {
 
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int n = Integer.parseInt(st.nextToken()), m = Integer.parseInt(st.nextToken()), x = Integer.parseInt(st.nextToken());
        int[][] Arr = new int[n + 1][n + 1];
 
        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 dis = Integer.parseInt(st.nextToken());
            Arr[start][end] = dis;
        }
        int ans = -1;
        for (int i = 1; i < n + 1; i++) {
            boolean[] vis = new boolean[n + 1];
            int[] dArr = new int[n + 1];
             ans = Math.max(ans,fun(Arr, dArr, vis, i, x) + fun(Arr,dArr,vis,x,i));
 
        }
 
        System.out.println(ans);
 
    }
 
    static int fun(int[][] Arr, int[] dArr, boolean[] vis, int start, int endIndex) {
        for (int i = 1; i < dArr.length; i++) {
            dArr[i] = Integer.MAX_VALUE;
            vis[i] = false;
        }
        dArr[start] = 0;
        vis[start] = true;
        for (int i = 1; i < Arr.length; i++) {
            if (!vis[i] && Arr[start][i] > 0) { //start노드와 인접한 노드거리 설정
                dArr[i] = Arr[start][i];
            }
        }
        for (int i = 1; i < Arr.length - 1; i++) { //모든 노드 돌아보기
            int min = Integer.MAX_VALUE;
            int index = -1;
 
            for (int j = 1; j < Arr.length; j++) {
                if (!vis[j] && dArr[j] != Integer.MAX_VALUE) { //한번도 방문한적없고 인접한경우 즉 인접노드
                    if (dArr[j] < min) { //가장짧은거리노드를 찾음
                        min = dArr[j];
                        index = j;
                    }
                }
            }
            vis[index] = true//가장 짧은 노드 방문
            for (int j = 1; j < Arr.length; j++) {
                if (!vis[j] && Arr[index][j] > 0) { //인접하고 방문한적없는 노드이고
                    if (dArr[j] > dArr[index] + Arr[index][j]) { // 이노드j를 거칠 경우 더 짧다면?
                        dArr[j] = dArr[index] + Arr[index][j]; // 거리 수정
                    }
                }
            }
 
        }
        return dArr[endIndex];
    }
 
}
 
cs