코딩테스트/알고리즘 문제풀이

[파이썬] 2798 : 블랙잭

지과쌤 2021. 8. 8.
반응형

문제

카지노에서 제일 인기 있는 게임 블랙잭의 규칙은 상당히 쉽다. 카드의 합이 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

import itertools itertools 라이브러리를 사용하여 원소들의 순열과 조합을 사용할 수 있다. 1. 순열 순열은 서로 다른 n개 중, r개를 나열하는 경우의 수로 permutations 함수를 사용한다. def permutation(sel..

earthteacher.tistory.com

파이썬은 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

댓글

💲 추천 글