92342번_양궁대회
https://programmers.co.kr/learn/courses/30/lessons/92342
문제 요약
1. 양궁대회에서 라이언이 어피치를 이기는 경우를 구해서 과녁 위치에 따라 몇 발을 맞추면 되는지 리스트로 출력해야한다.
2. 어피치가 모든 화살을 쏜 다음, 라이언이 어피치와 같은 개수의 화살을 쏜다.
3. 과녁 위치마다 과녁 점수가 다르고, 라이언이 어피치를 이기는 경우 중 점수 차이가 가장 큰 경우를 출력한다.
4. 라이언이 가장 큰 점수 차이로 우승할 수 있는 방법이 여러가지일 경우, 가장 낮은 점수를 더 맞힌 경우를 출력한다.
4번 조건 같은 경우,
[2,3,1,0,0,0,0,1,3,0,0]과 [2,1,0,2,0,0,0,2,3,0,0]를 비교하면 [2,1,0,2,0,0,0,2,3,0,0]를 return 해야한다.
라이언이 효율적으로 화살을 사용하기 위해서는 어피치가 이미 맞춘 점수는 아예 0발을 맞춰서 버리거나, 어피치보다 1발 더 맞춰서 그 점수를 가져올 수 있다.
어피치가 10점 과녁을 1발 맞췄을 경우, 라이언은 0발 맞추거나 2발 맞추는 경우 두 가지만 생각할 수 있다!
import copy
answer = []
maxV = 1
def cal(L, A):
apeach, lion = 0, 0
for idx in range(11):
if A[idx] == 0 and L[idx] == 0:
continue
elif A[idx] < L[idx]:
lion += (10 - idx)
else:
apeach += (10 - idx)
return lion - apeach
def compare(res, L):
global answer, maxV
if maxV < res:
answer = [copy.deepcopy(L)]
maxV = res
elif maxV == res:
answer.append(copy.deepcopy(L))
# solution 1
def solution(n, info):
global answer
def score(s, L, cnt):
if cnt == 11:
if sum(L) == n:
compare(cal(L, info), L)
elif sum(L) < n:
L[10] += n - sum(L)
compare(cal(L, info), L)
L[10] -= n - sum(L)
return
for i in range(s, 11):
L[i] = info[i] + 1
score(i + 1, L, cnt+1)
L[i] = 0
score(i + 1, L, cnt+1)
score(0, [0] * 11, 0)
if not answer:
return [-1]
answer.sort(key=lambda x: x[::-1])
return answer[-1]
lambda로 정렬해서 낮은 점수가 제일 높은 경우만 출력deepcopy 사용해줬다# solution 2
def solution(n, info):
global answer
def score(s, L, cnt):
if not cnt:
compare(cal(L, info), L)
return
if s == 10 and cnt:
L[10] = cnt
score(s+1, L, 0)
L[10] = 0
else:
if info[s]+1 <= cnt:
temp = info[s] + 1
L[s] = temp
score(s+1, L, cnt - temp)
L[s] = 0
score(s+1, L, cnt)
score(0, [0] * 11, n)
두 번째 방법은 점수를 매길 때 for문을 사용하지 않고, 함수에 인덱스(과녁 위치)를 같이 넘겨줘서 해당 인덱스에 바로 화살을 매겨줬다. 모든 경우를 확인하는 1번보다 2번이 훨씬 짧게 걸렸다.
1. cnt는 남은 화살의 개수
2. 라이언이 남은 화살이 어피치가 맞춘 화살+1 보다 클 경우, 해당 과녁에 화살 추가/ 적을 경우 라이언은 해당 과녁 0발
풀이 방법이 잘못된 줄 알고, 다른 풀이 방법으로 두 번 풀었다.
알고보니까 cal 함수에서 for문 범위를 잘못 설정해준 거였다...
뭔가 잘못됐을 때는 전체적으로 확인할 필요가 있다.