Algorithem/백준 PS with code

백준 #14891 - 톱니바퀴 : 구현

jamong5 2023. 5. 19. 12:24

(python3)

구현 아이디어

이 문제의 경우 4개의 톱니를 동시에 회전시키는 것 처럼 구현해줄 필요가 있었습니다. 톱니 상황을 하나씩 업데이트 하다 보면 의도한 방향으로 상호작용이 일어나지 않을 수 있기 때문에 이를 고려해줄 필요가 있습니다.

크게 2단계로 구현을 분리했습니다.

1단계 : N번 톱니를 r 방향으로 회전시킬 때, 현재 상황에서 회전될 모든 톱니들과 각 톱니의 회전 방향을 구한다.
이 단계에서는 현재 상황에서 톱니들의 사이에 일어날 상호작용만 체크하고 톱니 상황을 업데이트하지는 않습니다.

2단계 : 1단계에서 구한 정보를 토대로 톱니 방향을 회전시켜 톱니 상황을 업데이트한다.

구현 디테일

톱니의 상태를 배열로 나타내는데, 회전할때마다 배열의 모든 값을 밀거나 당기기는 방향으로 업데이트를 해줄 수 도 있지만, 어떤 톱니가 12시 방향을 가리키고 있는지, 인덱스를 짚어주는 int 값을 하나 따로 두는 방식으로도 관리해줄 수 있습니다.

 저는 톱니가 서로 맞닿는 (상호작용이 일어나는) 6개의 포인트들의 인덱스를 gi 라는 배열로 따로 저장하여 관리했습니다. (12시 방향을 가리키는 인덱스만 관리하는게 편할 것 같긴 합니다.)

굉장히 하드코딩을 했기 때문에... 톱니 수가 많아지면 1단계 알고리즘을 많이 고쳐야할 듯 합니다.

# https://www.acmicpc.net/problem/14891
def solution(input) : 
    """
    톱니바퀴 번호 = 1, 2, 3, 4
    톱니바퀴 초기 상태 G = [_,1,2,3,4]
    톱니바퀴의 붙어있는 지점 (index) 를 표현한 dict : gi = [12, 21, 23, 32, 34, 43] 이 인덱스를 수정하면서 톱니의 회전을 표현
    """

    # 기어 정보 받아오기 (12시부터 시계방향, N극 = 0, S극 = 1)
    G = [0,]
    for _ in range(4) :
        g = input().strip()
        gi = []
        for t in g :
            gi.append(int(t))
        G.append(gi)
    # 회전수 정보 받아오기
    K = int(input())
    # 회전할 톱니 번호와 방향 받아오기
    R = []
    for _ in range(K) :
        R.append(tuple(map(int, input().split())))
    # 톱니의 회전 상태를 표현해줄 gi 배열 생성
    gi = [2,6,2,6,2,6]

    def rotate(Gn, d) :
        """
        n번 기어를 d 방향으로 회전 (기어의 상호작용은 고려 X)
        """
        d = -d
        if Gn == 1 :
            gi[0]+=d
        elif Gn ==2 :
            gi[1]+=d
            gi[2]+=d
        elif Gn==3 :
            gi[3]+=d
            gi[4]+=d
        else :
            gi[5]+=d
        for i, g in enumerate(gi) :
            if g == 8 :
                gi[i] = 0
            elif g == -1 :
                gi[i] = 7
        
    def check_rotate_gear(M,r) :
        """
        M 번 기어를 r 방향으로 회전할 때 회전될 모든 기어와 방향을 list 로 묶어서 반환
        """
        rg = [(M,r)]
        diff_pole = [G[1][gi[0]] != G[2][gi[1]],
                     G[2][gi[2]] != G[3][gi[3]],
                     G[3][gi[4]] != G[4][gi[5]]]
        if M==1 :
            if diff_pole[0] :
                rg.append((2,-r))
                if diff_pole[1] :
                    rg.append((3,r))
                    if diff_pole[2] :
                        rg.append((4,-r))
        elif M==2 :
            if diff_pole[0] :
                rg.append((1,-r))
            if diff_pole[1] :
                rg.append((3,-r))
                if diff_pole[2] :
                    rg.append((4,r))
        elif M==3 :
            if diff_pole[1] :
                rg.append((2,-r))
                if diff_pole[0] :
                    rg.append((1,r))
            if diff_pole[2] :
                rg.append((4,-r))
        elif M==4 :
            if diff_pole[2] :
                rg.append((3,-r))
                if diff_pole[1] :
                    rg.append((2,r))
                    if diff_pole[0] :
                        rg.append((1,-r))
        return rg
    
    def rotate_all(M,r) :
        """
        M번 기어를 r 방향으로 회전할 때 상호작용을 고려하여 4개 기어를 모두 회전
        """
        rotate_list = check_rotate_gear(M,r)
        for i in rotate_list :
            rotate(*i)

    for r in R :
        rotate_all(*r)

    # 기어들의 12시 방향 극 확인
    gear_12 = [G[1][gi[0]-2], G[2][gi[2]-2], G[3][gi[4]-2], G[4][gi[5]-6]]
    # 점수 계산
    score = [1,2,4,8]
    final_score = 0
    for a,b in zip(gear_12,score) :
        final_score += a*b

    print(final_score)

solution(input)