여름의 서재

[SWEA] 4880_토너먼트 카드게임 (DFS 이용) 본문

알고리즘/SWEA

[SWEA] 4880_토너먼트 카드게임 (DFS 이용)

엉아_ 2021. 8. 24. 18:47
728x90

📕 문제

사다리 게임이 지겨워진 알고리즘 반 학생들이 새로운 게임을 만들었다. 가위바위보가 그려진 카드를 이용해 토너먼트로 한 명을 뽑는 것이다. 게임 룰은 다음과 같다.

1번부터 N번까지 N명의 학생이 N장의 카드를 나눠 갖는다. 전체를 두 개의 그룹으로 나누고, 그룹의 승자끼리 카드를 비교해서 이긴 사람이 최종 승자가 된다.

그룹의 승자는 그룹 내부를 다시 두 그룹으로 나눠 뽑는데, i번부터 j번까지 속한 그룹은 파이썬 연산으로 다음처럼 두개로 나눈다.


두 그룹이 각각 1명이 되면 양 쪽의 카드를 비교해 승자를 가리고, 다시 더 큰 그룹의 승자를 뽑는 방식이다.

다음은 4명이 카드를 비교하는 경우로, 숫자 1은 가위, 2는 바위, 3은 보를 나타낸다. 만약 같은 카드인 경우 편의상 번호가 작은 쪽을 승자로 하고, 처음 선택한 카드는 바꾸지 않는다.

 N명이 학생들이 카드를 골랐을 때 1등을 찾는 프로그램을 만드시오.

 

[입력]

첫 줄에 테스트 케이스 개수 T가 주어진다.  1T50

다음 줄부터 테스트 케이스의 별로 인원수 N과 다음 줄에 N명이 고른 카드가 번호순으로 주어진다. 4N100
카드의 숫자는 각각
 1은 가위, 2는 바위, 3은 보를 나타낸다.

 

[출력]

각 줄마다 "#T" (T는 테스트 케이스 번호)를 출력한 뒤, 1등의 번호를 출력한다.

 

💡 풀이법

1. 시작점과 끝점이 매개변수인 dfs 함수를 만듦.

2. 재귀 종료 조건을 정함. start와 end가 같다면 1명이 골라진 것이기 때문에 start를 반환.

3. 큰 집단을 두개의 집단으로 계속 나눠야 하기 때문에 반으로 나눠서 왼쪽, 오른쪽 재귀함수 돌림

4. 이제 가위바위보 함수를 만들어야함. 나는 키값을 왼쪽이 낸 패라고 보고, 오른쪽이 value의 0번째 패를 내면 왼쪽이 이기고, 1번째 패를 내면 오른쪽이 이기는 것으로 RSP라는 딕셔너리를 만듦.

5. 이제 이 딕셔너리를 이용해서 rsp라는 함수를 만듦.

6. 전에 나눈 왼쪽과 오른쪽을 매개변수로 넣어서 가위바위보 함수를 dfs 함수의 마지막에 반환함.

7. 인덱스는 0부터 시작이지만 사람은 1부터 시작이기 때문에 사람의 번호를 출력할때 +1 해서 출력.

 

RSP = {1: (3, 2), 2: (1, 3), 3: (2, 1)}
def rsp(a, b):
    if numbers[a] == numbers[b]:
        return a
    elif RSP[numbers[a]][0] == numbers[b]:
        return a
    elif RSP[numbers[a]][1] == numbers[b]:
        return b

def tournament(start, end):
    if start == end:
        return start

    left = tournament(start, (start + end)//2)
    right = tournament((start + end)//2 + 1, end)

    return rsp(left, right)

T = int(input())
for tc in range(1, T+1):
    N = int(input())
    numbers = list(map(int, input().split()))
    print('#{} {}'.format(tc, tournament(0, N-1)+1))
Comments