맛있는물회

[맛있는물회] <SWEA알고리즘> 4880번 "토너먼트 카드게임" 본문

IT/알고리즘

[맛있는물회] <SWEA알고리즘> 4880번 "토너먼트 카드게임"

맛있는물회 2020. 4. 7. 22:45

문제 조건


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

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

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




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

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


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

 

Input


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

다음 줄부터 테스트 케이스의 별로 인원수 N과 다음 줄에 N명이 고른 카드가 번호순으로 주어진다. 4N100

카드의 숫자는 각각
 1은 가위, 2는 바위, 3은 보를 나타낸다.

 

Output


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

 

생각한 아이디어


재귀함수를 사용하면 간단하게 해결 가능하다.

이진탐색을 생각하면 쉽게 풀 수 있다.

 

나눈 파티션에서 원소가 홀수 개수일때 어떻게 해야하는지에 신경을 써줘야한다. 나는 기저사례를 end - start <= 1 으로 해주어서 홀수일때는 즉, 3개일때 왼쪽 2개, 오른쪽 1개 이렇게해서 오른쪽은 무조건 비기게 설정을 하였다.

그렇게 나누고 나누어서 기저사례까지 간다면 if문으로 조정한 후 값을 만들어 내면된다! 

 

 

소스코드


def game(start,end):
    if end-start <= 1:  #base
        if (card[start][1] == card[end][1]) or (card[start][1] == 1 and card[end][1] == 3) or (card[start][1] == 2 and card[end][1] == 1)or (card[start][1] == 3 and card[end][1] == 2): #비기거나 start가 이김
            return (start,card[start][1])
        else :
            return (end, card[end][1])
    

    front = game(start,(start+end)//2)
    rear = game((start+end)//2+1,end)

    if (front[1] == rear[1]) or (front[1] == 1 and rear[1] == 3) or (front[1] == 2 and rear[1] == 1)or (front[1] == 3 and rear[1] == 2): #비기거나 front가 이김
        return front
    else :
        return rear

T = int(input())
for TC in range(1,T+1):
    N = int(input())
    arr = list(map(int,input().split()))
    card = list()
    for i in range(0,N):
        card.append((i,arr[i]))
    
    ans = game(0,N-1)

    print("#%d %d" %(TC, ans[0]+1))

 

*파이썬 문법 정리

Comments