알고리즘

[프로그래머스] 양궁 대회

맨날개발 2023. 3. 10. 21:54

문제 요약

라이언과 어피치가 양궁대결을 합니다. 총 n발을 화살을 쏘게 되며 점수별로 더 많은 화살을 맞춘 사람이 점수를 가져가게 됩니다. 만약 동일한 개수를 명중시킨 경우 어피치가 점수를 가져갑니다. 최종적으로 높은 점수를 획득한 사람이 우승하게 됩니다.

  • 예 : 10점과녁을 어피치가 2발, 라이언이 3발 -> 라이언이 10점 획득
  • 예 : 10점과녁을 어피치가 3발, 라이언이 3발 -> 어피치가 10점 획득

어피치가 맞춘 과녁 점수의 개수가 담긴 배열(10점부터 0점 순서대로)을 매개변수로 주어집니다. 이때 라이언이 가장 큰 점수차로 우승하기 위한 n발의 화살을 어떤 과녁에 맞혀야 하는지를 반환하면 됩니다. 만약 라이언이 우승할 수 없는 경우에는 -1이 담긴 배열을 반환합니다.

 

나의 생각

화살을 가장 효율적으로 사용하기 위해서는 각 점수마다 어피치가 맞춘 개수보다 1개를 더 많이 맞춰서 점수를 획득하거나, 0발을 맞춰서 지는 경우를 생각하였습니다. 이를 구현하기 위해서 BFS를 사용하기로 결정하였습니다.

반복문안에서 처리해야하는 코드는 크게 두가지로 생각해볼 수 있습니다.

  1. n발의 화살을 모둔 쏜 경우 스코어 계산
  2. 해당 점수에서 몇발의 화살을 쏠지 여부 적용
    • 10 - 1점까지 모두 화살을 쏜 후 남은 화살은 전부 0점으로 간주하여 queue에 추가합니다.
    • [그렇지 않은 경우 해당 점수에서] 0발을 쏘는 경우와, 어피치가 맞춘 개수 + 1 만큼 아직 쏘지 않은 화살이 남은 경우 queue에 추가합니다.

 

[CASE 23]을 통과하지 못한 경우 max가 0인 비긴 경우이기 때문에 조건을 추가해주어야 합니다.
function solution(n, info) {
    const queue = [[Array(11).fill(0), 0, 0]];
    let max = 0;
    let maxList = [-1];

    while (queue.length) {
        const [list, count, index] = queue.shift();

        if (count === n) {
            const score = info.reduce((acc, v, i) => {
                if (v > list[i]) {
                    acc -= 10 - i;
                } else if (v < list[i]) {
                    acc += 10 - i;
                }

                return acc;
            }, 0); 

            if (score > max) {
              max = score;
              maxList = list;
            } else if (score === max) {
              const isMax = [...list].sort((a, b) => b - a)
                .some((v, i) => maxList[i] < v);

              if (isMax) {
                maxList = list;
              }  
            }

            continue;
        }

        if (index === 10) {
          const newList = [...list];
          newList[index] = n - count;
          queue.push([newList, n, index + 1]);
        } else {
          queue.push([list, count, index + 1]);

          if (info[index] < n - count) {
            const newList = [...list];
            newList[index] = info[index] + 1;
            queue.push([newList, count + info[index] + 1, index + 1]); 
          }  
        }
    }

    if (max === 0) {
      return [-1];
    }

    return maxList;
}