CS/algorithm & data structure
[프로그래머스] 양궁대회 (파이썬 풀이)
hjkim0502
2022. 7. 7. 02:55
https://school.programmers.co.kr/learn/courses/30/lessons/92342
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
* 풀이 못 함
from itertools import combinations_with_replacement as cr
def solution(n, info):
# 중복조합으로 모든 경우 탐색하면서 정답 갱신
# 최대로 점수 차이가 클 때의 점수 분포 + 그 때의 점수 차이 값(max[-1])
max = [-1] * 12
for comb in cr(range(11), n):
cur = [0] * 12
# 점수별 화살 개수
for c in comb:
cur[10 - c] += 1
# 점수 차이 계산
for i in range(11):
# 라이언 점수 획득
if cur[i] > info[i]:
cur[-1] += 10 - i
# 어피치 점수 획득
elif info[i] != 0:
cur[-1] -= 10 - i
# 라이언이 우승하지 못하는 경우
if cur[-1] <= 0:
continue
# 기존의 점수 차이 최댓값을 갱신하는 경우
if cur[::-1] > max[::-1]:
max = cur
return [-1] if max[-1] <= 0 else max[:-1]
- 아이디어: 0 ~ 10의 점수를 n번 중복 허용하여 뽑기 -> 11Hn(중복조합), 각 경우마다 어피치와 비교하여 최대 점수차이에 해당하는 경우 갱신
- 리스트끼리 비교 연산자(>, <)를 사용하면 앞에서부터 확인하면서 같으면 넘기고 최초로 다른 그 지점에서 부등호 방향이 맞으면 바로 True 반환하고 종료 (그 뒤는 고려하지 않음)
def solution(n, info):
max = [-1] * 12
for win in range(1 << 10):
# 10 ~ 1의 점수별 화살 갯수, 0점 개수, 점수 차이
cur = [0] * 10 + [n, 0]
for i in range(10):
# 라이언 점수 획득
if win & (1 << i):
cur[-1] += 10 - i
cur[-2] -= info[i] + 1
cur[i] = info[i] + 1
# 어피치 점수 획득
elif info[i] != 0:
cur[-1] -= 10 - i
# 라이언이 지거나 화살을 n발 초과로 쏜 경우
if cur[-1] <= 0 or cur[-2] < 0:
continue
# cur가 기존에 저장된 max보다 좋을 경우
if cur[::-1] > max[::-1]:
max = cur
return [-1] if max[-1] <= 0 else max[:-1]
- 아이디어: 1~10점 중에 라이언이 획득한다고 가정하는 점수들에 대해 필요한 화살이 n개를 넘지 않고, 가장 큰 점수 차이로 이기면서 가장 낮은 점수를 더 많이 맞힌 경우 반환
- 비트 연산을 이용해 점수를 획득하는 모든 경우에 대해 각 상황에서 어피치와 점수차이 계산
- 획득하는 점수에 대해서는 어피치보다 1개 더 맞히고, 그렇지 않은 점수는 0개를 맞히며, 나머지 화살은 가장 낮은 점수를 더 많이 맞히는 것이 좋으므로 모두 0점을 맞힌다고 가정
- 중복조합보다 고려할 경우가 훨씬 적으므로 시간 효율이 훨씬 좋음 (11Hn = 20C10 >> 2 ** 10 = 1024)