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

Narcoker·2022년 9월 22일
0

코딩테스트

목록 보기
41/150

문제 설명

문제가 길어서 링크로 대체합니다.
https://school.programmers.co.kr/learn/courses/30/lessons/92342

풀이

라이언이 점수를 얻기 위해서는 어피치가 쏜 화살 수보다 1 많아야한다.
어피치의 과녁판을 순회하면서
목표 화살 수(어피치가 쏜 화살수 + 1) <= 남은 화살 수인 경우 화살을 쏜다.
남은 화살 수, 쏜 이후의 라이언의 과녁판, 다음 점수의 인덱스
를 파라미터로 가지고 재귀를 수행한다.

만약 화살 수가 음수라면 점수를 따낼 수 있었지만 화살 수가 부족했다는 뜻이므로
return 한다.

화살 수가 0 이면 정상적으로 화살을 쐈다는 의미이므로
점수를 계산한다.

점수 차가 0 인 경우는 비겼다는 것이므로 return 한다.
점수가가 최대차(score)보다 큰 경우 answer값과 최대차 값을 재할당한다.
점수차가 최대차와 같은 경우 적은 점수를 많이 획득한 값을
answer에 할당하고 return 한다.

이 로직은 각 배열을 reverse().join() 후 비교하면(숫자열로 강제 변환)
구할 수 있다.

재귀함수(search())가 끝나면 answer 값을 반환한다.

function solution(n, info) {
    let answer = [];
    let lionInfo = Array(11).fill(0);
    let score = 0;
    function search(arrow, lionInfo, index) {
        if (arrow < 0) return;

        if (arrow === 0) {
            let [apeachScore, lionScore] = [0, 0];
            let diff;
            for (let i = 0; i < 11; i++) { // 점수 계산
                if (info[i] || lionInfo[i]) {
                    info[i] - lionInfo[i] >= 0 ? apeachScore += 10 - i : lionScore += 10 - i;
                }
            }

            diff = lionScore - apeachScore;
            if (diff === 0) return;

            if (score < diff) { // 최대차인 경우
                score = diff;
                answer = lionInfo;
            } else if (score === diff) {
                if ([...answer].reverse().join("") < [...lionInfo].reverse().join(""))
                    answer = lionInfo;
            }
            return;
        }

        for (let i = index; i < 11; i++) {
            if (arrow > lionInfo[i]) {
                let nextLineInfo = [...lionInfo];
                if (info[i] + 1 < arrow) // 화살개수가 넉넉한 경우
                    nextLineInfo[i] = info[i] + 1;
                else { // 화살 개수가 모자란 경우
                    nextLineInfo[i] = arrow;
                }
                search(arrow - nextLineInfo[i], nextLineInfo, i + 1);
            }
        }
    }

    search(n, lionInfo, 0)
    return answer.length === 0 ? [-1] : answer
}

회고

재귀 함수 사용 시 객체를 파라미터로 넣으면 깊은 복사된 값이 아닌 얕은 복사된 값이 들어가기 때문에 항상 깊은 복사를 시행한 값을 파라미터로 넣어야한다.

재귀함수가 끝나면 변경한 값을 이전 값으로 돌려줄 것.
아니면 파라미터에서 바로 변경값을 넣던지..

profile
열정, 끈기, 집념의 Frontend Developer

0개의 댓글