Lv 2. 양궁대회

2025. 2. 28. 22:37·Algorithm & Data Structures/Programers

 

https://school.programmers.co.kr/learn/challenges?order=acceptance_desc&levels=2%2C3%2C4&languages=java&page=7

 

코딩테스트 연습 | 프로그래머스 스쿨

개발자 취업의 필수 관문 코딩테스트를 철저하게 연습하고 대비할 수 있는 문제를 총망라! 프로그래머스에서 선발한 문제로 유형을 파악하고 실력을 업그레이드해 보세요!

school.programmers.co.kr

 

 

 

📌 자바(Java)로 푸는 양궁대회 문제 풀이 🚀


🔎 문제 개요

이 문제는 프로그래머스 - 양궁대회 문제입니다.
라이언이 화살 n개를 사용하여 어피치보다 높은 점수를 얻는 방법을 찾아야 합니다.
단, 어피치의 화살 기록(info[])이 주어지며, 점수 차이가 가장 큰 경우를 선택해야 합니다.


💡 예제 입력

int n = 5;
int[] info = {2,1,1,1,0,0,0,0,0,0,0};

💡 예제 출력

[0,2,2,0,1,0,0,0,0,0,0]

라이언이 최적의 화살 배분을 했을 때,
어피치보다 높은 점수를 얻으면서 점수 차이가 가장 큰 경우를 반환해야 합니다.


🛠 알고리즘 접근 방식

이 문제를 해결하기 위해 백트래킹(DFS) 알고리즘을 활용합니다.

✏️ 주요 고려 사항

✔ 각 점수 영역(0~10)에서 화살을 어떻게 분배할지 탐색
✔ 어피치보다 1개 더 많이 맞히는 경우 vs 그냥 지나치는 경우 선택
✔ 점수 차이가 가장 큰 경우를 선택
✔ 점수 차이가 같은 경우, 낮은 점수를 더 많이 맞힌 경우를 선택


🔹 Java 코드 해설

import java.util.*;

class Solution {

    int[] answer;    // 최적의 화살 배분 저장
    int[] now;       // 현재 화살 배분 상태
    int maximum = 0; // 최대 점수 차이
    int score = 0;   // 어피치 초기 점수
    boolean found = false; // 적절한 배분이 존재하는지 확인

    public int[] solution(int n, int[] info) {
        answer = new int[11];
        now = new int[11];

        // 어피치의 총 점수 계산
        for (int i = 0; i < 10; i++) {
            if (info[i] != 0)
                score += (10 - i);
        }

        // DFS 탐색 시작
        dfs(0, n, 0, score, info);

        // 최적의 화살 배분이 없는 경우
        if (!found)
            return new int[]{-1};

        return answer;
    }

    public void dfs(int depth, int count, int sum, int s, int[] info) {
        // 10번째 화살까지 모두 탐색했을 경우
        if (depth == 10) {
            now[10] = count; // 남은 화살을 모두 마지막 칸에 사용
            int diff = sum - s; // 점수 차이 계산

            // 최대 점수 차이 갱신
            if (diff > maximum) {
                maximum = diff;
                found = true;
                answer = now.clone(); // 최적의 화살 배분 저장
            } 
            // 점수 차이가 같을 경우, 낮은 점수를 더 많이 맞힌 경우를 선택
            else if (diff == maximum) {
                if (isBetter(now, answer))
                    answer = now.clone();
            }

            now[10] = 0; // 원상 복구
            return;
        }

        // 어피치보다 1개 더 맞혀서 점수를 가져가는 경우
        if (count >= info[depth] + 1) {
            now[depth] = info[depth] + 1;

            if (info[depth] > 0)
                dfs(depth + 1, count - (info[depth] + 1), sum + (10 - depth), s - (10 - depth), info);
            else
                dfs(depth + 1, count - (info[depth] + 1), sum + (10 - depth), s, info);

            now[depth] = 0; // 원상 복구
        }

        // 해당 점수를 포기하는 경우
        dfs(depth + 1, count, sum, s, info);
    }

    // 점수 차이가 같을 때, 낮은 점수를 더 많이 맞힌 경우가 더 좋은 경우인지 판단
    private boolean isBetter(int[] candidate, int[] current) {
        for (int i = 10; i >= 0; i--) {
            if (candidate[i] > current[i])
                return true;
            else if (candidate[i] < current[i])
                return false;
        }
        return false;
    }
}

🔍 코드 설명

📌 1. 초기 값 설정

answer = new int[11];
now = new int[11];
  • answer[]: 최적의 화살 배분을 저장할 배열
  • now[]: 현재 화살 배분 상태를 저장할 배열

📌 2. 어피치의 초기 점수 계산

for (int i = 0; i < 10; i++) {
    if (info[i] != 0)
        score += (10 - i);
}
  • 어피치가 맞힌 점수 영역의 총 점수를 구함

📌 3. 백트래킹(DFS) 탐색

dfs(0, n, 0, score, info);
  • 점수 영역(0~10)을 순차적으로 탐색
  • count: 남은 화살 개수
  • sum: 현재 라이언 점수
  • s: 현재 어피치 점수

📌 4. 모든 점수를 탐색했을 때 (Base Case)

if (depth == 10) {
    now[10] = count;
    int diff = sum - s;

    if (diff > maximum) {
        maximum = diff;
        found = true;
        answer = now.clone();
    } 
    else if (diff == maximum) {
        if (isBetter(now, answer))
            answer = now.clone();
    }

    now[10] = 0;
    return;
}
  • 10개의 점수 탐색이 끝나면 남은 화살을 0점에 배분
  • 최대 점수 차이를 갱신
  • 점수 차이가 같다면 더 낮은 점수를 많이 맞힌 경우를 선택

📌 5. 라이언이 어피치보다 1개 더 맞히는 경우

if (count >= info[depth] + 1) {
    now[depth] = info[depth] + 1;

    if (info[depth] > 0)
        dfs(depth + 1, count - (info[depth] + 1), sum + (10 - depth), s - (10 - depth), info);
    else
        dfs(depth + 1, count - (info[depth] + 1), sum + (10 - depth), s, info);

    now[depth] = 0;
}
  • 어피치보다 1개 더 맞혀 점수를 가져가는 경우

📌 6. 점수를 포기하는 경우

dfs(depth + 1, count, sum, s, info);
  • 현재 점수를 포기하고 다음 점수로 진행

🔥 시간 복잡도 분석

연산 최악의 경우 수행 횟수 시간 복잡도
dfs 호출 2^10 (1024번) O(2^10) ≈ O(1024)

✅ 완전 탐색이지만 범위가 작아 충분히 가능


🏆 정리

✅ 핵심 포인트

✔ DFS(백트래킹)으로 모든 경우의 수 탐색
✔ 점수 차이가 가장 큰 경우를 선택
✔ 점수 차이가 같다면, 낮은 점수를 많이 맞힌 경우를 선택


이 글이 도움이 되셨다면 좋아요와 공유 부탁드립니다!

 

 

'Algorithm & Data Structures > Programers' 카테고리의 다른 글

Lv 3. 보행자 천국  (0) 2025.03.05
Lv 3. 기둥과 보  (0) 2025.03.03
Lv 2. 조이스틱  (0) 2025.02.05
Lv 2. 숫자블록  (0) 2025.02.03
Lv3. 길찾기 게임  (1) 2025.01.24
'Algorithm & Data Structures/Programers' 카테고리의 다른 글
  • Lv 3. 보행자 천국
  • Lv 3. 기둥과 보
  • Lv 2. 조이스틱
  • Lv 2. 숫자블록
Geisha
Geisha
개발 일기
  • Geisha
    Geisha
    Geisha
  • 전체
    오늘
    어제
    • 분류 전체보기 (305) N
      • Algorithm & Data Structures (231) N
        • BOJ (90) N
        • SWEA (1)
        • Programers (136)
        • Data Structures (3)
      • DB (21)
        • SQL (15)
        • RDBMS (2)
      • Java (1)
        • Class (1)
      • Spring (5)
        • Spring MVC (1)
        • Annotations (1)
      • CS (36)
        • 운영체제 (13)
        • 네트워크 (5)
      • Tool (6)
        • Git (5)
        • AWS (1)
      • Project (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    전위순회
    프로그래머스
    백준
    algorithm
    구현
    PriorityQueue
    DynamicProgramming
    BFS
    Union-Find
    동적계획법
    baekjoon
    dp
    unionfind
    Java
    위상정렬
    Stack
    이진탐색
    다익스트라
    후위순회
    스택
    백트래킹
    경로압축
    알고리즘
    dfs
    Dijkstra
    binarySearch
    투포인터
    유니온파인드
    이분탐색
    programmers
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
Geisha
Lv 2. 양궁대회
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.