[プログラマー]ランキング(レベル3)


📝質問リンク
プログラマ>グラフィックス>ランキングの表示
🔑問題キー
DFS,BFSを用いて探索しても順位は判断できない.
結局、今日また区組長に解決を手伝ってもらいました.
この問題はフロリダとシエルのアルゴリズムを適用する必要があるという.
まず、Floyd Warshallアルゴリズムについて説明します.▶ フロリダとシャーロットの概念を理解する
Floyd Warshallアルゴリズムを理解しています
最終的に各選手と選手の戦績を一列に並べた.
  • Floyd Warshallの2 D配列を作成します:rank[n+1][n+1](選手数とインデックスを調整するために使用されます)
    1-1. 0に設定し、残りは無限に設定します.
  • 相手との戦績を調べる.
    2-1. results[]で勝てば1に設定(注意、これは一方通行!、勝負が決まっています.)
  • Floyd Warshallアルゴリズム
  • を適用
    しかし、ランキングはどうやって決まるのでしょうか.😥😥😥
    (フロリダとシャロのアルゴリズムを利用した解題方法が見つかりました!!いつ一人で解題できるのでしょうか?😙)
    ✔優先度が決められる場合は?
    順位は、自分以外の全ての選手と試合をした場合にのみ決定される.
    私たちはfloydwarhallですべての選手との試合戦績を取った.
  • 自分がいなければ全ての選手と試合をする場合、人数を確認すれば正解が得られる.
  • コードをもう一度見てみましょう.🔍
    💻問題を解く
    public int solution(int n, int[][] results) {
        int[][] rank = new int[n+1][n+1];       // 인덱스 1부터 시작하려고
        int inf = 1000000;                      // 방문 불가능한 경우
    
        // 자기 자신과 싸우는 경우만 0으로 설정, 나머지는 inf로 초기화
        for(int i=1;i<n+1;i++){
            for(int j=1;j<n+1;j++){
                if(i==j)    rank[i][j] = 0;
                else        rank[i][j] = inf;
            }
        }
    
        // 상대 전적이 있는 경우 check
        // 단 방향으로만 체크해야한다. 승패가 정해져 있기 때문에
        for(int i=0 ; i< results.length; i++){
            rank[results[i][0]][results[i][1]] = 1;
        }
    
        // 플로리다 와샬 알고리즘으로 승부가 가능한 지 확인
        // k는 거쳐가는 사람
        for(int k=1;k<n+1;k++){
            // i는 나
            for(int i=1;i<n+1;i++){
                // j는 상대
                for(int j=1;j<n+1;j++){
                    if(rank[i][j] > rank[i][k] + rank[k][j]){
                        rank[i][j] = rank[i][k] + rank[k][j];
                    }
                }
            }
        }
    
        // 경기를 했는지 여부 체크
        boolean[] check = new boolean[n+1];
        // 모두 경기했다고 초기 설정
        Arrays.fill(check, true);
        // i는 나
        for(int i=1;i<n+1;i++){
            // j는 상대방
            for(int j=1;j<n+1;j++){
                // 나 자신과의 싸움이 아니면서, 서로 싸움을 한 전적이 없는 경우 false로 체크
                if(i != j && rank[i][j] == inf && rank[j][i] == inf){
                    check[i] = false;
                    break;              // 한 명이라도 싸움을 안했다면, i는 순위를 매길수 없기에 break문으로 빠져나옴
                }
            }
        }
    
        int answer=0;
        // 싸운적이 있는 사람만 count
        for(int i=1;i<n+1;i++){
            if(check[i])   answer++;
        }
        return answer;
    }
    完全なソースの表示(Git)
    [参考]
    ランキングC++(グラフ)[プログラマー]