알고리즘/알고리즘_swea

[Python][SWEA] 6808. 규영이와 인영이의 카드게임

Jerry_K 2024. 5. 8. 09:21
 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com


🗒️ 파이썬 코드 풀이

def permutation() : # 인영이 카드의 모든 조합을 인영이 카드와 비교 
    global cnt
    if len(card_lst) == 9 :
        sum = 0
        for i in range(9):
            if lst_gu[i] > card_lst[i]:
                sum += (lst_gu[i] + card_lst[i])
            if sum >= 86 : 
                cnt += 1
                break                

    else : 
        for i in range(9):  # 9중 for문
            if lst_in[i] not in card_lst :  
                card_lst.append(lst_in[i])
                permutation()  # 다음 조합을 위해서 꼭 필수
                card_lst.pop()
                

T = int(input())
for tc in range(1,T+1) :
    lst_gu = list(map(int,input().split())) # 규영이 카드
    lst_in = [] # 인영이 카드

    for i in range(1,19) :  # 규영이 카드 찾기
        if i not in lst_gu :
            lst_in.append(i)

    cnt = 0 
    card_lst = []
    permutation()
    print(f"#{tc} {cnt} {362880-cnt}")

 

1. 규영의 카드와 카드의 순서는 정해져있지만 인영이의 카드는 조합을 통해 구성해야한다.

(인영이의 카드는 9장뿐이니 재귀함수를 떠올린다.)

 

2. 먼저 간단히 반복문을 통해 규영가 가진 카드를 찾아준다.

 

3. 인영이가 가진 카드의 조합을 담을 리스트 (card_lst)를 만들어준다.

 

4. permutation if ~else 구문 중 else 구문을 먼저 살펴보자.

else 구문 :

모든 인영이의 카드 숫자 중 card_lst에 없는 카드 숫자를 넣어준다.

함수를 다시 호출여 이 과정을 반복하고, 재귀 함수의 호출이 다 끝나면 다음 조합을 위해 pop()을 해준다.

(이 과정에서 인영이 카드는 모든 경우 수가 만들어진다.)

 

5. permutation if ~else 구문 중 if 구문을 살펴보자.

if 구문 : 

재귀함수에서 수만~수억개의 card_lst 값들이 만들어지는데, 리스트의 길이가 9인 경우로 필터링한다.

다 만들어진 card_lst의 하나 하나 값들은  규영이 카드와 크기를 비교하고 승자를 카운트한다.

 

1~18을 모두 더한 수는 171로, 그 중 반 이상만 차지해도 승리를 예측 할 수 있다. 

따라서 기준을 86보다 크거나 같은 경우에 cnt +1을 해주고 바로 break를 했다.

 

 

📌 문제 코멘트

우선 문제를 풀면서 인영,규영 이름이 엄청 헷갈렸다...  사실 마지막에 출력 정답 값을 보면서  총 경우의수 362880에서 잘 빼주어 출력 하면 되기때문에, 누가 이기든 너무 신경 안써도 된다.

 

그리고 재귀함수 else 구문에 조합에서 어려움을 느꼈다.

어떻게 저 하나의 for문으로 수많은 조합을 나타낼 수 있었는지 한참을 헤매었다.

근데 여기서 주목해야 할 것은 재귀함수라는 것이다.  그렇기 때문에 단순 for문 한개가 아닌 9중 for문이 되는것이다.

 

조합에서는 재귀 함수의 호출을 다 마무리하면 꼭 뒤에  pop() 함수가 필요하다. 

다른 조합을 위해서 각 층마다 pop을 해줘서 뒤에서부터 조합을 하나 하나 만들어준다.

 

마지막으로 승부 결정 지을때, 나는 끝까지 점수를 다 체크하였다.

하지만 간단히 86점만 넘기면 승리 확정을 지을 수 있다.  이러한 간단한 방법들을 기억하자.

 

이 문제는 나 혼자의 힘으로 못 풀었다...

어짜피 로직만 잘 구성하면 코드는 쉬울거니, 재귀함수를 너무 무서워하지말자 !


📚 문제

규영이와 인영이는 1에서 18까지의 수가 적힌 18장의 카드로 게임을 하고 있다.

한 번의 게임에 둘은 카드를 잘 섞어 9장씩 카드를 나눈다. 그리고 아홉 라운드에 걸쳐 게임을 진행한다.

한 라운드에는 한 장씩 카드를 낸 다음 두 사람이 낸 카드에 적힌 수를 비교해서 점수를 계산한다.

높은 수가 적힌 카드를 낸 사람은 두 카드에 적힌 수의 합만큼 점수를 얻고,

낮은 수가 적힌 카드를 낸 사람은 아무런 점수도 얻을 수 없다.

이렇게 아홉 라운드를 끝내고 총점을 따졌을 때, 총점이 더 높은 사람이 이 게임의 승자가 된다.

두 사람의 총점이 같으면 무승부이다.

이번 게임에 규영이가 받은 9장의 카드에 적힌 수가 주어진다.

규영이가 내는 카드의 순서를 고정하면, 인영이가 어떻게 카드를 내는지에 따른 9!가지 순서에 따라

규영이의 승패가 정해질 것이다.

이 때, 규영이가 이기는 경우와 지는 경우가 총 몇 가지 인지 구하는 프로그램을 작성하라.


[입력]

첫 번째 줄에 테스트 케이스의 수 T가 주어진다.

각 테스트 케이스의 첫 번째 줄에는 아홉 개의 정수가 공백으로 구분되어 주어진다.

각 정수는 1이상 18이하이며, 같은 정수는 없다.

규영이는 정수가 주어지는 순서대로 카드를 낸다고 생각하면 된다.


[출력]

각 테스트 케이스마다 ‘#x’(x는 테스트케이스 번호를 의미하며 1부터 시작한다)를 출력하고 한 칸을 띄운 후,

인영이가 카드를 내는 9! 가지의 경우에 대해 규영이가 게임을 이기는 경우의 수와 게임을 지는 경우의 수를

공백 하나로 구분하여 출력한다.