알고리즘/BFS & DFS & 백트래킹

프로그래머스 | 순위 - java

세댕댕이 2022. 8. 26. 19:35
 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

# 핵심

플로이드 와샬 알고리즘?

 

개 어렵다. 혼자 못풀었다. 솔직히 남의 코드 보고 거의 베꼈다

(참고) https://gom20.tistory.com/178

 

 

<플로이드 와샬 알고리즘>

-> 직접적으로 연결된 노드가 아니더라도, K번 노드를 통해 간접적으로 연결될 수도 있다!

아래 왼쪽 짤에서도, 5번 노드는 2번 노드와만 직접적으로 연결되어 있지만, 2번 노드를 거쳐서 1번 노드와 3번 노드로도 이동할 수 있다.

오른쪽 짤에서도 2번 노드는 4번 노드와 직접 연결되어있지 않지만, 3번 노드를 거쳐간다면 4번 노드로 이동할 수 있게 된다.




[2번 노드를 거쳐가는 경우]
(1) 5 < 2, 2 < 1 이라면 5 < 1 이다
(2) 5 < 2, 2 < 3 이라면 5 < 3 이다
(3) 1 < 2, 2 > 5 이라면 아무것도 안된다
등등등... 


[3번 노드를 거쳐가는 경우]
(1) 2 < 3, 3 < 4 이라면 3 < 4 이다
....

 

즉, \

출발 노드 < 경유 노드, 경유 노드 < 도착 노드 인 경우 = 출발 노드 < 도착 노드

출발 노드 > 경유 노드, 경유 노드 > 도착 노드 인 경우 = 출발 노드 > 도착 노드

 

출발 노드와 도착 노드가 직접 대결을 하지 않았더라도 간접적으로 둘 간의 결과를 알아낼 수 있다.

 

플로이드 와살 알고리즘은 보통 다익스트라 알고리즘과 함께 최단거리 계산에 사용되는 대표적인 알고리즘이지만, 본 문제에서는 최단거리 계산의 용도가 아니라 응용 버전이다..

 

플로이드 와샬에 대해 더 알고싶으면 아래의 유튜브를 참고하자.. 이분의 영상이 참 도움이 됐다.

https://www.youtube.com/watch?v=9574GHxCbKc 

 

# 통과 코드

class Solution {

    public int solution(int n, int[][] results) {
        int[][] adj = new int[n][n];

        for (int[] result : results) {
            // 양방향 연결
            adj[result[1] - 1][result[0] - 1] = 1; // 승
            adj[result[0] - 1][result[1] - 1] = -1; // 패
        }

        for(int k = 0; k < n; k++) { // k번 노드를 거쳐가는 경우
            for(int i = 0; i < n; i++) { // 출발 노드
                for(int j = 0; j < n; j++) { // 도착 노드
                    // i > k && k > j ==> i > j
                    if(adj[i][k] == 1 && adj[k][j] == 1) {
                        adj[i][j] = 1; // 출발 노드 승
                        adj[j][i] = -1; // 도착 노드 패
                    }
                    // i < k && k < j ==> i < j
                    if(adj[i][k] == -1 && adj[k][j] == -1) {
                        adj[i][j] = -1; // 출발 노드 패
                        adj[j][i] = 1; // 도착 노드 승
                    }
                }
            }
        }

        int cnt = 0;
        for (int[] ints : adj) {
            int tmp = 0;
            // 해당 노드와 간접/직접적으로 연결된 노드가 n - 1개라면 순위를 확정할 수 있다.
            // * n - 1인 이유 = 본인 제외
            for (int anInt : ints) {
                if(anInt != 0) tmp++;
            }
            if(tmp == n - 1) cnt++;
        }
        return cnt;
    }
}

 

 

어떻게 이런 생각을 잘 할 수 있을까

진짜 아직도 부족한게 너무 많구나 다시한번 느끼고 간다..