알고리즘 문제 풀기

[프로그래머스 12978] 배달 (Java)

Solu- 2021. 7. 5. 18:54

[링크]https://programmers.co.kr/learn/courses/30/lessons/12978)

나의 코드

class Solution {
    public int solution(int N, int[][] road, int K) {
        int answer = 0;

        // 경로 값의 무한값 설정 (c의 최대값 * N-1)
        final int INF = 20000 * (N-1);

        // 지나간 마을인지 확인하는 배열 생성
        boolean[] check = new boolean[N];   // 초기값 : false
        int[] value = new int[N];

        // 경로를 저장하는 N*N의 배열 생성
        int[][] table = new int[N][N];

        // table 초기화
        for (int i = 0; i < N; i++) {

            // value도 여기서 초기화
            value[i] = INF;

            for (int k = 0; k < N; k++) {
                table[i][k] = INF;
            }
            table[i][i] = 0;    // 자신에겐 0
        }

        // road의 입력받은 경로 값 저장
        for (int[] r : road) {
            // 양방향이므로 반대도 저장
            // 도시간의 도로는 여러개가 있을 수 있기 때문에
            // 값이 적은 하나의 도로만 남겨두기로 함

            if (table[r[0] - 1][r[1] - 1] > r[2]) {
                table[r[0] - 1][r[1] - 1] = r[2];
                table[r[1] - 1][r[0] - 1] = r[2];
            }

        }
        // 테이블 값 확인
        /*
        for (int[] y : table) {
            for (int x : y) {
                System.out.print(x + " ");
            }
            System.out.println();
        }
        */

        // 문제에서는 무조건 1번에서 출발하기 때문에, 1번부터 확인
        // 마을은 1~N번마을까지 있고, 실제로는 0~N-1로 접근하니까 헷갈리지 않도록 주의
        int start = 0;
        value[start] = 0;   // 출발점이기 때문에 0으로 변경

        do {
            check[start] = true;    // 방문 기록 체크

            for (int i = 0; i < N; i++) {
                // 이전의 최소값 보다 지금까지 값 + 현재 도로 값 이 작으면 갱신

                if (value[start] + table[start][i] < value[i]) {
                    // 갱신
                    value[i] = value[start] + table[start][i];
                }
            }

            // 다음 출발 값 확인
            start = -1; // 출발값 초기화
            int min = INF;

            // 아직 방문하지 않았고, 경로값이 가장 적은 노드를 탐색
            for (int i = 0; i < N; i++) {
                if ((check[i] == false) && (value[i] < min)) {
                    start = i;
                    min = value[i];
                }
            }

        } while(start != -1);

        // 각 노드별 계산된 최소값 확인
        /*
        for (int a : value) {
            System.out.print(a + " ");
        }

        System.out.println();
        */

        for (int val : value) {
            if (val <= K) {
                answer++;
            }
        }

        return answer;
    }
}

경로 탐색에 대한 알고리즘은 필요할 것 같아서 개념을 확인하고 풀어보았다.
다익스트라 알고리즘의 기본 개념은 노드를 탐색하면서 현재까지의 경로가 더 적을 경우 그 경로를 우선순위로 한다는 것이다. 정확한 개념 풀이는 다른 블로그를 참조하는 게 좋겠다.

모범 답안

class Solution {
    public int solution(int N, int[][] road, int K) {

        int matrix[][] = new int[N][N];
        for(int i=0;i<N;i++)
            for(int j=0;j<N;j++)
                matrix[i][j] = 0;

        for(int i=0;i<road.length;i++) {
            if(matrix[road[i][0]-1][road[i][1]-1] == 0 || 
              matrix[road[i][0]-1][road[i][1]-1] > road[i][2])
                matrix[road[i][0]-1][road[i][1]-1] = 
                    matrix[road[i][1]-1][road[i][0]-1] = road[i][2];
        }

        boolean visits[] = new boolean[N];
        int costs[] = new int[N];
        for(int i=0;i<N;i++) {
            visits[i] = false;
            costs[i] = Integer.MAX_VALUE;
        }

        costs[0] = 0;
        int target = 0;
        while(true) {
            visits[target] = true;
            for(int i=0;i<N;i++)
                if(matrix[target][i] > 0) {
                    if( costs[i] > costs[target] + matrix[target][i])
                        costs[i] = costs[target] + matrix[target][i];
                }

            target = -1;
            for(int i=0;i<N;i++)
                if(!visits[i]) {
                    if(target == -1 || costs[target] > costs[i])
                        target = i;
                }

            if(target == -1)
                break;
        }

        int answer = 0;
        for(int i=0;i<N;i++) {
            if(costs[i] <= K)
                answer++;
        }

        return answer;
    }
}

대부분 같은 형식이다. 다만 어느 블로그 글에서 초기 값을 Integer.MAX_VALUE로 했을 때 문제가 생긴다는 글이 있어 나의 경우는 MAX 값을 별도의 수로 지정했다.
그 부분을 제외하고는 아래의 코드가 훨씬 간결하다고 생각한다.