[백준] 9017_크로스 컨트리(Javascript)

잭슨·2024년 3월 5일
0

알고리즘 문제 풀이

목록 보기
39/130
post-thumbnail

문제

BOJ9017_크로스 컨트리

코드

// 한 팀은 6명, 상위 4명의 점수를 합하여 계산
// 결승점을 통과한 순서대로 점수 부여
// 가장 낮은 점수를 얻는 팀이 우승
// 6명의 주자가 참가하지 못한 팀은 점수 계산에 포함하지 않는다.
// 동점인 경우 다섯 번째 주자가 가장 빨리 들어온 팀이 우승
// 적어도 한 팀은 우승한다. 모든 선수는 등수가 존재한다.
// 동점의 경우에는 다섯 번째 주자가 가장 빨리 들어온 팀이 우승하게 된다.

const filePath = process.platform === 'linux' ? '/dev/stdin' : './Javascript/input.txt';
const input = require('fs').readFileSync(filePath).toString().trim().split('\n');
const T = +input.shift();
for (let i = 0; i < T; i++) {
    const N = +input[i * 2];
    const players = input[i * 2 + 1].split(' ').map(Number);
    solution(N, players);
}

function solution(N, players) {
    // 1. 팀별 주자 수 구하기
    const teams = new Set(players);
    const teamObj = {};
    [...teams].forEach((e) => (teamObj[e] = 0));
    players.forEach((e) => (teamObj[e] += 1));

    // 2. 주자가 6명이 되지 않는 팀 제외
    for (let teamNum in teamObj) {
        if (teamObj[teamNum] < 6) delete teamObj[teamNum];
    }

    // 3. 팀별 각 주자의 점수 구하기
    const scoreObj = {};
    let score = 1;
    players.forEach((num) => {
        if (teamObj.hasOwnProperty(num)) {
            if (scoreObj[num]) scoreObj[num].push(score++);
            else {
                scoreObj[num] = [];
                scoreObj[num].push(score++);
            }
        }
    });

    // 4. 팀별 4등까지의 점수의 합, 5등까지의 점수의 합 구하기
    for (let teamNum in scoreObj) {
        const scoreToFour = scoreObj[teamNum].slice(0, 4).reduce((acc, cur) => (acc += cur), 0);
        const scoreToFive = scoreObj[teamNum].slice(0, 5).reduce((acc, cur) => (acc += cur), 0);
        scoreObj[teamNum] = [scoreToFour, scoreToFive];
    }

    // 5. 점수가 제일 작은 팀 구하기
    const teamNums = Object.keys(teamObj);
    let minScore = scoreObj[teamNums[0]];
    let answer = teamNums[0];
    for (let i = 1; i < teamNums.length; i++) {
        if (minScore[0] === scoreObj[teamNums[i]][0]) {
            minScore = minScore[1] < scoreObj[teamNums[i]][1] ? minScore : scoreObj[teamNums[i]];
            answer = minScore[1] < scoreObj[teamNums[i]][1] ? answer : teamNums[i];
        } else {
            minScore = minScore[0] < scoreObj[teamNums[i]][0] ? minScore : scoreObj[teamNums[i]];
            answer = minScore[0] < scoreObj[teamNums[i]][0] ? answer : teamNums[i];
        }
    }
    console.log(answer);
}

풀이

  1. 팀별로 주자가 몇 명인지 구하여 '팀 번호-주자 수' 꼴로 객체에 저장한다.
const teams = new Set(players);
const teamObj = {};
[...teams].forEach((e) => (teamObj[e] = 0));
players.forEach((e) => (teamObj[e] += 1));

console.log(teamObj);

  1. 주자가 6명이 되지 않는 팀은 객체에서 제거해준다.
for (let teamNum in teamObj) {
        if (teamObj[teamNum] < 6) delete teamObj[teamNum];
}

console.log(teamObj);

  1. 팀별로 각 주자의 점수를 구하여 '팀 번호-[주자들의 점수]' 꼴로 객체에 저장한다.
const scoreObj = {};
let score = 1;
players.forEach((num) => {
  if (teamObj.hasOwnProperty(num)) {
    if (scoreObj[num]) scoreObj[num].push(score++);
    else {
      scoreObj[num] = [];
      scoreObj[num].push(score++);
    }
  }
});

console.log(scoreObj);

  1. 동점의 경우에는 다섯 번째 주자가 가장 빨리 들어온 팀이 우승하게 되므로 4번째 주자까지의 점수의 합과, 5번째 주자까지의 점수의 합을 각 팀별로 구해서 객체에 저장한다.
for (let teamNum in scoreObj) {
        const scoreToFour = scoreObj[teamNum].slice(0, 4).reduce((acc, cur) => (acc += cur), 0);
        const scoreToFive = scoreObj[teamNum].slice(0, 5).reduce((acc, cur) => (acc += cur), 0);
        scoreObj[teamNum] = [scoreToFour, scoreToFive];
}

  1. 4번 주자까지의 점수의 합이 더 적은 팀의 번호를 answer 변수에 저장한다. 만약 4번 주자까지의 점수의 합이 같다면, 5번 주자까지의 점수의 합과 비교해서 점수가 더 적은 팀의 번호를 저장한다.
const teamNums = Object.keys(teamObj);
let minScore = scoreObj[teamNums[0]];
let answer = teamNums[0];
for (let i = 1; i < teamNums.length; i++) {
  if (minScore[0] === scoreObj[teamNums[i]][0]) {
    minScore = minScore[1] < scoreObj[teamNums[i]][1] ? minScore : scoreObj[teamNums[i]];
    answer = minScore[1] < scoreObj[teamNums[i]][1] ? answer : teamNums[i];
  } else {
    minScore = minScore[0] < scoreObj[teamNums[i]][0] ? minScore : scoreObj[teamNums[i]];
    answer = minScore[0] < scoreObj[teamNums[i]][0] ? answer : teamNums[i];
  }
}
console.log(answer);

profile
지속적인 성장

0개의 댓글