2022 KAKAO BLIND RECRUITMENT
LEVEL 2
라이언과 어피치가 양궁 결승 경기를 치른다. 경기 규칙은 다음과 같다.
n
발을 쏜 후 라이언이 n
발을 쏜다.현재 어피치가 n
발을 다 쏘고 라이언이 화살을 쏠 차례다. 라이언이 어피치를 상대로 가장 큰 점수차로 이기기 위해서는 n
발의 화살을 어떤 과녁 점수에 맞혀야 하는지 구하는 solution
함수를 작성하시오. 가장 큰 점수차로 이기는 경우가 여러 가지일 경우 가장 낮은 점수를 더 많이 맞힌 경우를 return
하시오. (만약 라이언이 우승할 수 있는 경우가 없다면 [-1]
을 return
)
n
n
≤ 10info
info
의 길이 = 11info
의 원소 총합 = n
n
발의 화살을 어떤 과녁 점수에 맞혀야 하는지 담은 정수 배열[-1]
DFS로 라이언이 n
발의 화살로 만들 수 있는 점수판을 탐색하며 maxDiff
와 result
를 갱신한다.
maxDiff
를 선언, 초깃값은 0
/ 가장 큰 점수차를 만드는 라이언의 점수판을 담을 배열 result
를 선언, 초깃값은 빈배열dfs
선언apeachScore
, 라이언의 누적점수를 담은 ryanScore
, 현재까지 라이언이 쏜 화살 개수를 담은 cnt
, 현재 어느 과녁 점수를 살펴볼 것인지를 담은 idx
(idx
= 10 - 과녁 점수), 현재 라이언의 점수판을 담은 ryanInfo
n
보다 크면 탐색 중지 (cut > n
일때 return
)maxDiff
보다 큰지 비교 후 탐색 중지maxDiff
보다 크다면 해당 점수차로 maxDiff
를 갱신하고 result
를 ryanInfo
로 갱신maxDiff
와 같다면 result
에 ryanInfo
를 추가n > cnt
)info[idx] > 0
)info[idx] === 0
)dfs
함수 호출 apeachScore = 0
, ryanScore = 0
, cat = 0
, idx = 0
, ryanInfo = new Array(11).fill(0)
result
에 담긴 점수판이 1개 이상일 때, 가장 낮은 점수를 더 많이 맞힌 경우가 앞으로 오도록 result
를 정렬return
되도록 구현되지 않아서였다. 해당 부분을 추가하니 모든 테스트케이스를 통과할 수 있었다.maxDiff > 0
) result[0]
을, 이길 수 없는 경우 [-1]
을 return
function solution(n, info) {
// 1-1. 가장 큰 점수차를 담을 maxDiff 선언
let maxDiff = 0;
// 1-2. 가장 큰 점수차를 만드는 라이언의 점수판을 담을 배열 result를 선언
let result = [];
// 2. 재귀함수 dfs 선언
function dfs(apeachScore, ryanScore, cnt, idx, ryanInfo) {
// 2-1. 현재까지 라이언이 쏜 화살의 개수가 n보다 크면 탐색 중지
if (cnt > n) return;
// 2-2. 10점부터 0점까지 점수계산이 모두 끝난 경우 탐색 중지
if (idx > 10) {
const diff = ryanScore - apeachScore;
// 2-2-1. 현재 점수차가 maxDiff보다 큰 경우
if (diff > maxDiff) {
maxDiff = diff; // maxDiff를 diff로 갱신
ryanInfo[10] = n - cnt; // 남은 화살로 모두 0점 과녁을 맞힘
result = [ryanInfo]; // result를 ryanInfo로 갱신
}
// 2-2-2. 현재 점수차가 maxDiff와 같은 경우
if (diff === maxDiff) {
ryanInfo[10] = n - cnt; // 남은 화살로 모두 0점 과녁을 맞힘
result.push(ryanInfo); // result에 ryanInfo 추가
}
return;
}
// 2-3. Case 1 : 라이언이 득점
if (n > cnt) {
const newRyanScore = ryanScore + (10 - idx);
const newRyanInfo = [...ryanInfo];
newRyanInfo[idx] = info[idx] + 1; // 어피치보다 해당 과녁 점수를 1발 더 맞힘
const newCnt = cnt + info[idx] + 1;
dfs(apeachScore, newRyanScore, newCnt, idx + 1, newRyanInfo);
}
// 2-4. Case 2 : 어피치가 득점
if (info[idx] > 0) {
const newApeachScore = apeachScore + (10 - idx);
dfs(newApeachScore, ryanScore, cnt, idx + 1, ryanInfo);
}
// 2-5. Case 3 : 아무도 득점하지 못함
if (info[idx] === 0) {
dfs(apeachScore, ryanScore, cnt, idx + 1, ryanInfo);
}
}
// 3. dfs 함수 호출
dfs(0, 0, 0, 0, new Array(11).fill(0));
// 4. result에 담긴 점수판이 1개 이상일 때,
// 가장 낮은 점수를 더 많이 맞힌 경우가 앞으로 오도록 result를 정렬
if (result.length > 1) {
result.sort((a, b) => {
for (let i = 10; i >= 0; i--) {
if (a[i] !== b[i]) return b[i] - a[i];
}
return 0;
})
}
// 5. 라이언이 이길 수 있는 경우 result[0]을, 이길 수 없는 경우 [-1]을 return
return (maxDiff > 0) ? result[0] : [-1];
}