양궁대회

최민수·2023년 3월 14일
0

알고리즘

목록 보기
37/94
import copy

⭐️
answer = []
maxDiff = -1

def calc(ryan, apeach):
    sumL, sumA = 0, 0
    for idx, (l, a) in enumerate(zip(ryan, apeach)):
        if l > a:
            sumL += (10-idx)
        elif l == a == 0:
            continue
        else:
            sumA += (10-idx)
    return sumL - sumA


def dfs(apeach, ryan, n, idx):
    global maxDiff, answer
    
    # Termination 조건
    if idx == 11:
        # 화살이 남았으면 마지막 0점에 몰아주기
        if n > 0:
            ryan[10] = n
        scoreDiff = calc(ryan, apeach)
        if scoreDiff <= 0: # 라이언이 우승할 방법X
            return
        temp = copy.deepcopy(ryan)
        if scoreDiff > maxDiff:
            maxDiff = scoreDiff
            answer = [temp]
        elif scoreDiff == maxDiff:
            answer.append(temp)
        return
    
    # 점수 따는 경우
    if apeach[idx] < n:
        ryan.append(apeach[idx]+1)
        dfs(apeach, ryan, n - (apeach[idx]+1), idx+1)
        ryan.pop()
    
    # 점수 못따는 경우
    ryan.append(0)
    dfs(apeach, ryan, n, idx+1)
    ryan.pop()
    

def solution(n, info):
    global answer
    
    # 완전 탐색 - 2^11
    # 아예 0개를 쏘거나, 어피치+1 개를 쏘거나
    dfs(info, [], n, 0)
    
    # 정답형식 처리
    if len(answer) == 0:
        return [-1]
    
    # 가장 낮은 점수 개수가 많은 경우 선택
    answer.sort(key=lambda x: x[::-1], reverse=True)
    
    return answer[0]

처음에는 아이디어를 생각하지 못했다.

아예 화살 0개를 쏘거나(점수 포기), 어피치+1 개를 쏘거나(점수 쟁취)

또, 구현도 만만치 않았다.
고민한 결과, DFS 백트래킹이 따져야 할 경우의 수도 그렇고 구현하기에 가장 수월해 보였다.

중간 중간에 세밀한 조건 처리도 중요했다. Apeach와 Ryan이 모두 0점일 경우 점수 없음, answer에 후보 답을 넣을 때 deepcopy로 넣어야 한다는 점 등.

프로그래머스 연습문제, https://school.programmers.co.kr/learn/challenges

profile
CS, 개발 공부기록 🌱

0개의 댓글