[2022 KAKAO BLIND RECRUITMENT] 양궁대회

ByEunwoo
algorithm

https://school.programmers.co.kr/learn/courses/30/lessons/92342

level: 2

알고리즘: 완전탐색 (DFS)

문제를 잘 읽자.
info의 i번째 원소는 과녁의 10 - i 점을 맞힌 화살 개수입니다. ( i는 0~10 사이의 정수입니다.)

풀이 Logic

  1. 완전 탐색과 깊이 우선 탐색(DFS)을 사용하여 모든 가능한 경우를 탐색합니다.

  2. DFS 함수는 각 점수(10점부터 0점까지)에 대해 라이언이 화살을 쏠지 말지를 결정합니다.

  3. 모든 화살을 사용했거나 마지막 점수(0점)에 도달하면, 라이언과 어피치의 점수를 계산합니다.

  4. 라이언이 이기는 경우 중 가장 큰 점수 차이를 찾고, 그때의 화살 배치를 저장합니다.

  5. 점수 차이가 같은 경우, 가장 낮은 점수에 더 많은 화살을 쏜 경우를 선택합니다.







해답 코드

function solution(n, info) {
  let max = 0;
  let answer = [-1];
  let ryan = Array(11).fill(0);
 
  function DFS(level, count) {
    // 기저 조건(base case)
    if (level == 11 || count == 0) {
      if (count > 0) ryan[10] += count; // 마지막에 남은 화살이 있다면 0점에 할당하고, 계산 후 다시 제거합니다.
 
      let sum = 0;
      for (let i = 0; i < 11; i++) {
        if (ryan[i] > info[i]) {
          // ryan이 apeach보다 해당 level에서 더 많이 맞춘 경우
          sum += 10 - i;
        } else if (info[i] > 0) {
          // 해당 level에서 ryan보다 더 많이 맞췄거나, 같은 화살 수인 경우
          sum -= 10 - i;
        }
      }
 
      if (sum > 0 && sum >= max) {
        if (sum > max || isLowerScoreBetter(ryan, answer)) {
          max = sum;
          answer = [...ryan];
        }
      }
 
      if (count > 0) ryan[10] -= count;
      return;
    }
 
    // ryan이 가지고 있는 화살 수가 apeach가 해당 level에서 맞힌 화살 수보다 많은 경우
    if (count > info[level]) {
      ryan[level] = info[level] + 1;
      DFS(level + 1, count - ryan[level]);
      ryan[level] = 0; // 백트래킹  -  이전 단계로 되돌아감
    }
 
    DFS(level + 1, count);
  }
 
  function isLowerScoreBetter(ryan, answer) {
    for (let i = 10; i >= 0; i--) {
      // 가장 낮은 점수를 더 맞이 맞힌 경우 (문제 조건)
      if (ryan[i] !== answer[i]) {
        return ryan[i] > answer[i];
      }
    }
    return false;
  }
 
  DFS(0, n);
  return answer;
}

코드 해설

백트래킹

ryan[level]을 통해서 이전 단계로 되돌아감으로써


if (count > info[level]) {
  ryan[level] = info[level] + 1;
  DFS(level + 1, count - ryan[level]);
  ryan[level] = 0; // 백트래킹  -  이전 단계로 되돌아감
}

isLowerScoreBetter 함수

function isLowerScoreBetter(ryan, answer) {
  for (let i = 10; i >= 0; i--) {
    // 가장 낮은 점수를 더 맞이 맞힌 경우 (문제 조건)
    if (ryan[i] !== answer[i]) {
      return ryan[i] > answer[i];
    }
  }
  return false;
}

가장 낮은 점수를 더 맞이 맞힌 경우 (문제 조건) 에 의해서 i가 10부터 0까지 돈다. i가 10일 경우 문제에서 10점이라고 하였기 때문에.


다듬기 전 코드

function solution(n, info) {
  var answer = [-1];
 
  let max = 0;
  let ryan = new Array(info.length).fill(0);
 
  function dfs(level, arrow) {
    // 기저 조건
    if (level === 11 || arrow === 0) {
      if (arrow > 0) ryan[10] += arrow;
 
      let sum = 0;
      for (let i = 0; i < info.length; i++) {
        if (ryan[i] > info[i]) {
          // ryan[i] <= info[i] 이건 둘 다 0점일 경우도 포함되기 때문에 안됌
          sum += 10 - i;
        } else if (info[i]) {
          sum -= 10 - i;
        }
      }
 
      if (sum > 0 && sum > max) {
        max = sum;
        answer = [...ryan];
      } else if (sum > 0 && sum === max) {
        for (let i = 10; i >= 0; i--) {
          if (ryan[i] !== answer[i]) {
            if (ryan[i] > answer[i]) {
              max = sum;
              answer = [...ryan];
            }
            break;
          }
        }
      }
 
      if (arrow > 0) ryan[10] -= arrow;
      return;
    }
 
    if (arrow > info[level]) {
      ryan[level] = info[level] + 1;
      dfs(level + 1, arrow - ryan[level]);
      ryan[level] = 0;
    }
 
    dfs(level + 1, arrow);
  }
 
  dfs(0, n);
 
  return answer;
}
Posted inalgorithm
Written byEunwoo