본문 바로가기

알고리즘/백준

[백준 / 구현] 9017 : 크로스 컨트리 (JavaScript)

728x90

난이도 : 실버3

문제 설명

문제

크로스 컨트리 달리기는 주자들이 자연적인 야외의 지형에 만들어진 코스를 달리는 운동 경기이다. 경주 코스는 일반적으로 4에서 12 킬로미터이며, 숲이나 넓은 땅을 통과하는 풀과 흙으로 된 지면과 언덕과 평평한 지형을 포함한다. 이 경기는 주자들의 개인성적을 매기고, 이를 가지고 팀의 점수를 계산한다. 

한 팀은 여섯 명의 선수로 구성되며, 팀 점수는 상위 네 명의 주자의 점수를 합하여 계산한다. 점수는 자격을 갖춘 팀의 주자들에게만 주어지며, 결승점을 통과한 순서대로 점수를 받는다. 이 점수를 더하여 가장 낮은 점수를 얻는 팀이 우승을 하게 된다. 여섯 명의 주자가 참가하지 못한 팀은 점수 계산에서 제외된다. 동점의 경우에는 다섯 번째 주자가 가장 빨리 들어온 팀이 우승하게 된다.

 

예를 들어, 다음의 표를 살펴보자.

 

등수 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
A B C C A C B D A A C A C C A
점수 1 n/a 2 3 4 5 n/a n/a 6 7 8 9 10 11 12

팀 B 와 D 는 선수의 수가 여섯이 아니므로, 점수를 받을 수 없다. 팀 A 의 점수는 18 (1+4+6+7)이고, 팀 C 의 점수는 18 (2+3+5+8)이다. 이 경우 두 팀의 점수가 같으므로 다섯 번째로 결승점을 통과한 선수를 고려한다, A 팀의 다섯 번째 선수의 점수가 C 팀의 다섯 번째 선수의 점수보다 적으므로 A 팀이 우승팀이 된다.

모든 선수들의 등수가 주어질 때, 우승팀을 구하는 프로그램을 작성하라. 각 팀의 참가 선수가 여섯보다 작으면 그 팀은 점수 계산에서 제외됨을 주의하라. 여섯 명 보다 많은 선수가 참가하는 팀은 없고, 적어도 한 팀은 참가 선수가 여섯이며, 모든 선수는 끝까지 완주를 한다고 가정한다.

입력

입력 데이터는 표준입력을 사용한다. 입력은 T 개의 테스트 케이스로 주어진다. 입력 파일의 첫 번째 줄에 테스트 케이스의 수를 나타내는 정수 T 가 주어진다. 두 번째 줄부터는 두 줄에 하나의 테스트 케이스에 해당하는 데이터가 주어진다. 각 테스트 케이스의 첫 번째 줄에는 하나의 정수 N (6 ≤ N ≤ 1,000)이 주어진다. 두 번째 줄에는 팀 번호를 나타내는 N 개의 정수 t1, t2, …, tN 이 공백을 사이에 두고 주어진다. 각 팀은 1 과 M(1 ≤ M ≤ 200)사이의 정수로 표현된다.

출력

출력은 표준출력을 사용한다. 하나의 테스트 케이스에 대한 우승팀의 번호를 한 줄에 출력한다. 

예제 입력 1

2
15
1 2 3 3 1 3 2 4 1 1 3 1 3 3 1
18
1 2 3 1 2 3 1 2 3 3 3 3 2 2 2 1 1 1

예제 출력 1

1
3

 

풀이

const filePath = process.platform === 'linux' ? "/dev/stdin" : "./input.txt";
const input = require('fs').readFileSync(filePath).toString().trim().split("\n");

const testcase = Number(input.shift());

for (let t = 0; t < testcase; t++){
    const totalNum = Number(input.shift());
    const ranking = input.shift().trim().split(" ").map(Number);
    let team = []; // 각 팀 정보를 저장할 객체 배열
    let eachTeamNum = {}; // 각 팀 별 인원 수
    const rightTeam = new Set(); // 조건에 맞는 팀

    ranking.forEach((num) => {
        if (!eachTeamNum[num]){
            eachTeamNum[num] = 1;
        } else {
            eachTeamNum[num]++;
            if (eachTeamNum[num] === 6){
                rightTeam.add(num)
            }
        }
    })

    rightTeam.forEach((num) => {
        team[num] = {'teamNum' : num, 'person' : 0, 'score' : 0, 'fifthScore' : 0};
    })

    let score = 0;
    for (let i = 0; i < totalNum; i++){
        let num = ranking[i];

        if (rightTeam.has(num)) {
            score ++;
            team[num].person++; // 사람 수 증가
            if (team[num].person < 5) {
                team[num].score += score;
            } else {
                if (team[num].person === 5) {
                    team[num].fifthScore = score;
                }
            }
        }
    }

    team.sort((a, b) => {
        if (a.score !== b.score) {
            return a.score - b.score;
        } else {
            return a.fifthScore - b.fifthScore;
        }
    });

    console.log(team[0].teamNum);   

}

 

shift()를 사용하여 input에 받은 전체 입력값을 하나하나 받아온다.

shift() 메서드는 배열에서 첫 번째 요소를 제거하고, 제거된 요소를 반환한다. 이 메서드는 배열의 길이를 변하게 한다.

 

team은 각 팀 별 정보를 저장한 객체 배열이다.

[ {팀 번호: n, 사람 수: n, 상위 4명 점수: n, 5번째 선수 점수: n}, {...}, ... ] 형태로 표현된다.

 

eachTeamNum은 조건을 만족하는 팀을 판별하기 위해 팀 별 사람 수를 저장한 객체이다.

{팀 번호: 사람수, ...}

 

rightTeam은 조건을 만족한 팀을 저장한 set 이다.

 

forEach를 사용하여 ranking 배열을 돌면서 각 팀 별 사람 수를 저장하고, 6명이 된다면 이 팀을 rightTeam에 넣는다.

forEach를 다 돌면 rightTeam에는 조건을 만족한 팀만 저장된다. 이 팀에 대한 정보를 team에 초기화한다.

rightTeam.forEach((num) => {
        team[num] = {'teamNum' : num, 'person' : 0, 'score' : 0, 'fifthScore' : 0};
    })

 

ranking을 다시 돌면서 조건을 만족한 팀의 점수를 계산한다.

rightTeam.has() 함수로 해당 팀이 조건을 만족하는지 확인한 뒤, 조건을 만족한다면 score을 1씩 증가하며 해당 팀의 점수를 계산한다. 상위 4명 점수까지만 계산하고, 5번째 선수는 fifthScore에 따로 저장한다.

 

team에 저장된 객체 배열을 정렬한다.

team.sort((a, b) => {
        if (a.score !== b.score) {
            return a.score - b.score;
        } else {
            return a.fifthScore - b.fifthScore;
        }
    });

a, b의 score가 같지 않다면 이를 비교하여 오름차순으로, 점수가 같다면 fifthScore를 비교하여 오름차순으로 정렬한다.

 

정렬을 마치면 team 배열의 가장 앞에 있는 팀이 우승자가 된다.

 

 

 

처음에는 조건을 만족하지 않는 팀의 점수도 함께 계산했는데, 문제를 다시 보니 조건을 만족하지 않는 팀의 점수는 n/a 처리되어 있었다. 문제를 읽고 결과를 손으로 확인한 뒤에 코드를 짜는 게 좋을 듯하다.

반응형