문제
카지노에서 제일 인기 있는 게임 블랙잭의 규칙은 상당히 쉽다. 카드의 합이 21을 넘지 않는 한도 내에서, 카드의 합을 최대한 크게 만드는 게임이다. 블랙잭은 카지노마다 다양한 규정이 있다.
한국 최고의 블랙잭 고수 김정인은 새로운 블랙잭 규칙을 만들어 상근, 창영이와 게임하려고 한다.
김정인 버전의 블랙잭에서 각 카드에는 양의 정수가 쓰여 있다. 그 다음, 딜러는 N장의 카드를 모두 숫자가 보이도록 바닥에 놓는다. 그런 후에 딜러는 숫자 M을 크게 외친다.
이제 플레이어는 제한된 시간 안에 N장의 카드 중에서 3장의 카드를 골라야 한다. 블랙잭 변형 게임이기 때문에, 플레이어가 고른 카드의 합은 M을 넘지 않으면서 M과 최대한 가깝게 만들어야 한다.
N장의 카드에 써져 있는 숫자가 주어졌을 때, M을 넘지 않으면서 M에 최대한 가까운 카드 3장의 합을 구해 출력하시오.
입력
첫째 줄에 카드의 개수 N(3 ≤ N ≤ 100)과 M(10 ≤ M ≤ 300,000)이 주어진다. 둘째 줄에는 카드에 쓰여 있는 수가 주어지며, 이 값은 100,000을 넘지 않는 양의 정수이다.
합이 M을 넘지 않는 카드 3장을 찾을 수 있는 경우만 입력으로 주어진다.
출력
첫째 줄에 M을 넘지 않으면서 M에 최대한 가까운 카드 3장의 합을 출력한다.
예제 입력 1 복사
5 21
5 6 7 8 9
예제 출력 1 복사
21
예제 입력 2 복사
10 500
93 181 245 214 315 36 185 138 216 295
예제 출력 2 복사
497
일단 문제의 의도는 브루트포스지만, itertools를 사용하여 답을 구해봤다. (1)
그리고, 다중 for문을 사용하여 브루트포스로도 답을 구해봤다. (2)
1. itertools
2021.08.06 - [<공부>/[Algorithm]] - [파이썬] 경우의 수 (순열, 조합) 구하기 - itertools
파이썬은 itertools를 통해 순열과 조합을 바로 구할 수 있게 해준다.
따라서, 리스트에서 3개의 수를 뽑아 한 튜플 세트로 만든 후 리스트에 넣었고 이 리스트를 선형탐색하여 3개의 수의 합을 구해 조건에 맞춰 최대값을 갱신한다.
2. 다중 for문
첫번째 for문에서는 첫번째 수,
두번째 for문에서는 두번째 수,
세번째 for문에서는 세번째 수 잡고
세번째 for문부터 순차적으로 이후의 숫자와 조합해 체크한 후, 두번째 for문에서 다음 수로 넘어간다.
그리고, 다시 세번째 for문에서 두번째 for문에서 선택한 수 다음 수부터 조합을 시작.
두번째 for문도 다 돌고난 후, 첫번째 for문도 다음 수로 돈다.
이런식으로 모든 수를 하나씩 순회하여 경우의 수를 만들 수 있다.
import itertools
class Blackjack :
def blackjackItertools(self, n, m, cardList) :
#m에 최대한 가까운 카드 3장의 합
maxSum = 0
#조합 사용하여 모든 경우 구하고 그중 조건 만족하는 제일 큰 경우
resultList = list(itertools.permutations(cardList, 3))
#각 경우의 수(튜플)의 합계를 구하면서 max값 갱신
for tuple in resultList :
newTuple = list(tuple)
if sum(newTuple)>m :
continue
else :
maxSum = max(maxSum, sum(newTuple))
print(maxSum)
def blackjackBruteForce(self, n, m, cardList):
#m에 가까운 최대값
maxSum = 0
#Brute Force
for firstPickIndex in range(n):
for secondPickIndex in range(firstPickIndex+1, n):
for thirdPickIndex in range(secondPickIndex+1, n):
if cardList[firstPickIndex] + cardList[secondPickIndex] + cardList[thirdPickIndex] > m:
continue
else:
maxSum = max(maxSum, cardList[firstPickIndex]+cardList[secondPickIndex]+cardList[thirdPickIndex])
print(maxSum)
if __name__ == "__main__" :
case1 = Blackjack()
#input
n, m = map(int, input().split())
cardList = list(map(int, input().split()))
print("-----Using Itertools-----")
case1.blackjackItertools(n, m, cardList)
print("-----Using Brute Force-----")
case1.blackjackBruteForce(n, m, cardList)
'코딩테스트 > 알고리즘 문제풀이' 카테고리의 다른 글
[파이썬] 7568 : 덩치 (0) | 2021.08.20 |
---|---|
[파이썬] 2231 : 분해합 (0) | 2021.08.12 |
[파이썬] 10872 : 팩토리얼 (0) | 2021.07.28 |
[파이썬] 1002 : 터렛 (0) | 2021.07.28 |
[파이썬] 3053 : 택시 기하학 (0) | 2021.07.28 |
댓글