[BOJ/백준-Python]2798번 - 블랙잭

2798번 - 블랙잭

문제

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

해결할 방법을 생각해보자.💡

첫 줄에서 카드 개수 N과 숫자 합의 한도 M을 받아주자.

N, M = map(int, input().split())

두 번째 입력 줄에서는 N장의 카드들을 받아서 리스트에 넣어주자.

cards = list(map(int, input().split()))

그리고 카드 3장을 골랐을 때의 모든 경우의 수를 담아줄 리스트 하나를 생성

all_case = []

이제 준비가 완료되었으면 예제를 통해서 생각해보자.

만약 카드 갯수 N이 4로 4장이고, 그 카드들이 1, 2, 3, 4라고 생각해보자.

여기서 3장을 뽑았을 경우의 모든 경우의수는 다음과 같다.

  1. 1 2 3
  2. 1 2 4
  3. 1 3 4
  4. 2 3 4

1, 2, 3, 4 이렇게 4개가 있을 때 맨 앞의 선택은 두 번째 까지만 반복한다. 따라서 범위를 받은 숫자 N에서 2를 빼주면 된다.

for i in range(N-2):

그리고 만약에 첫 카드를 1로 골랐을 경우에는, 2 3, 2 4, 3 4 이런 식으로 카드를 고를 수 있다.

두 번째 선택할 카드로 2와 3을 고를 수 있다는 이야기가 되는데, 이 경우에는 위 반복문 내 i에서 1을 더한 값부터 시작해 N까지 반복시켜주면 된다.

왜냐하면 i가 1일 때, 그 다음 선택으로 2나 3이 들어갈 수 있기 때문이다.

	for j in range(i+1, N):

그 다음으로 만약 첫, 두 번째 카드가 1과 2로 고정되어 있는 경우일 때는

세 번째 카드로 3이나 4가 선택될 수 있다.

따라서 위 반복문 j보다 1이 큰 수부터 시작해 N까지의 범위로 잡아줄 수 있다.

		for k in range(j+1, N):

이렇게 3중 반복문을 만들어 주었으면, 카드를 세 장을 선택한 경우를 아까 만들어둔 all_case 리스트에 담아주자.

			card = [cards[i], cards[j], cards[k]]
    		all_case.append(card)

그러면 all_case에는 다음과 같은 값들이 들어가 있을 것이다.

[[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]

이제 여기서 우리는 합계를 구해야한다. 따라서 sum을 각각 적용시켜준다.

all_sum_case = list(map(sum, all_case))

그런데 문제에서 중요한 접은, 합계가 입력값에 주어진 M보다 크면 안된다는 것이다.

따라서 한 번 필터링 해줘야할 필요가 있다.

all_sum_case2 = []

for i in all_sum_case:
    if i <= M:
        all_sum_case2.append(i)

필터링으로 M보다 작거나 같은 합계들을 모은 리스트를 다시 만들어줬다.

이제 어떤 수가 가장 M과 가까운지 판단해야한다.

양, 음에 상관없이 M과 차이가 가장 적은 수가 가장 가까운 수가 될것이다.

따라서 all_sum_case2 들의 원소들에서 M을 빼주고 그 절대값들을 담는 리스트를 만들어주자.

compare_diff = list(map(lambda x : abs(x - M), all_sum_case2))

이러면 compare_diff에는 M과의 거리들이 담겨있다. 여기서 가장 작은 값의 인덱스를 찾아서 저장해주자.

answer_index = compare_diff.index(min(compare_diff))

이제 아까 합계가 있던 리스트에서 방금 구한 인덱스를 사용해서 가장 가까운 합을 출력해주면 끝!

print(all_sum_case2[answer_index])

코드💻

N, M = map(int, input().split())
cards =  list(map(int, input().split()))
all_case = []
for i in range(N-2):
    for j in range(i+1, N):
        for k in range(j+1, N):
            card = [cards[i], cards[j], cards[k]]
            all_case.append(card)

all_sum_case = list(map(sum, all_case))
all_sum_case2 = []

for i in all_sum_case:
    if i <= M:
        all_sum_case2.append(i)

compare_diff = list(map(lambda x : abs(x - M), all_sum_case2))
answer_index = compare_diff.index(min(compare_diff))
print(all_sum_case2[answer_index])

해결 로그

문제 푼 날짜 체크
2022-06-20
   
   
   
   

2022

[web]jQuery 복습 3

1 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]jQuery 복습 2

13 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]jQuery 복습 1

14 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]JavaScript 정리4

5 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]JavaScript 정리3

10 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]JavaScript 정리2

7 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]JavaScript 정리1

8 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]CSS 기초 정리

11 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]HTML 기초 정리

8 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[Pandas]pandas 연습

3 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

맨 위로 이동 ↑

2021

[Python기초]module

1 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

맨 위로 이동 ↑