본문 바로가기
PS 문제 풀이/Baekjoon

[BOJ] 백준 14891 톱니바퀴

by 까망 하르방 2021. 2. 21.
반응형

출처: https://www.acmicpc.net/problem/14891

 Input 

10101111

01111101

11001110

00000010

2

3 -1

1 1

 

 Output 

7

 

총 K번 회전시킨 이후 4개의 톱니바퀴 점수 합을 출력합니다.

    - 1번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 1점

    - 2번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 2점

    - 3번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 4점

    - 4번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 8점

 

[3]번 바퀴를 반시계방향으로 회전시킨다.

    [4]번 바퀴는 N-S극 규칙으로 시계방향으로 한 번 회전한다.

    * 3번 바퀴가 회전하기 전의 극의 정보로 인접한 바퀴의 회전 여부 결정

    [2]번 바퀴는 S-S극으로 동일하기 때문에 변화가 없으며,

    [1]번 바퀴에는 변화가 없다.

 

[1]번 바퀴를 시계방향으로 회전시킨다.

[2]번 바퀴는 S-N 규칙으로 인해 반시계 방향으로 회전한다.

[3]번 바퀴는 S-N 규칙으로 인해 시계방향으로 회전한다.

[4]번 바퀴는 N-N으로 같기 때문에 변화가 없다.

 

결과는 아래와 같습니다.

각 톱니바퀴의 12시 방향 점수를 구하면

▶ 1 + 2 + 4 = 7

 

* 톱니바퀴는 회전하기 시작한 지점에서 양옆으로만 회전시킨다.

    톱니바퀴의 회전이 연쇄반응으로 되돌아 오지는 않는다. 

 

[구현] 각 톱니바퀴의 톱니는 List로 구현 

- 인접한 톱니바퀴의 맞닿은 극의 톱니는 2번째 6번째 요소입니다.

- 회전이 끝난 후, 12시 방향의 톱니는 첫번째 원소 값으로 정의하였습니다.

[시계 방향]

[반시계 방향]


import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);        
        
        Machine machine = new Machine();
        
        // 4개의 톱니바퀴에 대한 정보를 입력받는다.
        for(int i=0; i<4; i++) {
            String str = sc.next();
            
            Gear gear = new Gear();
            for(int j=0; j<str.length(); j++) {
                int teeth = Integer.parseInt(str.substring(j, j+1));
                gear.saw.add(teeth);
            }
            machine.gears.add(gear);
        }
        
        int rotateCnt = Integer.parseInt(sc.next());
        
        // 회전하기
        while(rotateCnt-- > 0) {
            // 회전 톱니바퀴 번호 (리스트는 시작인덱스가 '0'이므로 입력받은 것에서-1을 해줘야 한다.)
            int idx = Integer.parseInt(sc.next()) - 1;
            // 회전 방향(시계 or 반시계 방향)
            int direction = Integer.parseInt(sc.next());
            
            machine.run(idx,direction);
        }
        
        int answer = 0;
        for(int i=0; i<4; i++) {
            
            Gear gear = machine.gears.get(i);
            int target = gear.saw.get(0);
            if(target == 0) continue;
            
            // 2의 i승 형태를 이용
            answer += Math.pow(2, i);
        }
        System.out.println(answer);
    }
}

class Machine{
    // 시계 & 반시계 방향
    static final int FORWARD = 1;
    static final int RERVERSE = -1;
    List<Gear> gears;
    
    public Machine() {
        gears = new ArrayList<>();
    }

    public void run(int idx, int direction) {
        Gear gear = gears.get(idx);
        leftChain(idx, direction);
        rightChain(idx, direction);
        gear.rotate(direction);
    }

    

    private void leftChain(int idx, int direction) {
        // 왼쪽에 영향을 미칠 톱니바퀴가 없으면(제일 왼쪽 톱니바퀴라면) stop
        if(idx <= 0) return;
        
        // 맞닿은 극을 비교한다.
        // 극이 같다면 더 이상의 영향은 없다.
        if(gears.get(idx).saw.get(6) == gears.get(idx-1).saw.get(2)) return;
        // 극이 다르다면 현재 톱니바퀴에 대한 진행방향에 따른 처리를 해줘야 한다.
        else {
            // 현재 바퀴가 시계방향이면 왼쪽 바퀴는 반시계 방향이다.
            if(direction == FORWARD) {
                leftChain(idx-1, RERVERSE);
                // 왼쪽 바퀴도 회전하기 전에 그 다음 왼쪽 바퀴에 영향을 주는지 처리한 뒤에 회전을 한다.
                gears.get(idx-1).rotate(RERVERSE);
            }
            // 현재 바퀴가 반시계방향이면 왼쪽 바퀴는 시계 방향이다.
            else if(direction == RERVERSE) {
                leftChain(idx-1, FORWARD);
                // 왼쪽 바퀴도 회전하기 전에 그 다음 왼쪽 바퀴에 영향을 주는지 처리한 뒤에 회전을 한다.
                gears.get(idx-1).rotate(FORWARD);
            }
        }
    }
    
    private void rightChain(int idx, int direction) {
        // 오른쪽에 영향을 미칠 톱니바퀴가 없으면(제일 오른쪽 톱니바퀴라면) stop
        if(idx >= gears.size()-1) return;
        // 맞닿은 극을 비교한다.
        // 극이 같다면 더 이상의 영향은 없다.
        if(gears.get(idx).saw.get(2) == gears.get(idx+1).saw.get(6)) return;
        // 극이 다르다면 현재 톱니바퀴에 대한 진행방향에 따른 처리를 해줘야 한다.
        else {
            // 현재 바퀴가 시계방향이면 오른쪽 바퀴는 반시계 방향이다.
            if(direction == FORWARD) {
                rightChain(idx+1, RERVERSE);
                // 오른쪽 바퀴도 회전하기 전에 그 다음 오른쪽 바퀴에 영향을 주는지 처리한 뒤에 회전을 한다.
                gears.get(idx+1).rotate(RERVERSE);
            }
            // 현재 바퀴가 반시계방향이면 오른쪽 바퀴는 시계 방향이다.
            else if(direction == RERVERSE) {
                rightChain(idx+1, FORWARD);
                // 오른쪽 바퀴도 회전하기 전에 그 다음 오른쪽 바퀴에 영향을 주는지 처리한 뒤에 회전을 한다.
                gears.get(idx+1).rotate(FORWARD);
            }
        }
    }
}

class Gear{
    // 시계 & 반시계 방향
    static final int FORWARD = 1;
    static final int RERVERSE = -1;
    
    List<Integer> saw;
    public Gear() {
        saw = new ArrayList<>();
    }
    
    
    public void rotate(int direction) {
        // 시계 방향 회전인 경우
        if(direction == FORWARD) {
            // 제일 뒤에 있는 원소가 제일 앞으로 와서 12시 방향의 자리가 된다.
            // 나머지 원소는 자동적으로 밀려난다.
            saw.add(0, saw.remove(saw.size()-1));
        }
        // 반시계 방향 회전인 경우
        else if(direction == RERVERSE) {
            // 제일 앞에 있던 원소를 제일 뒤로 보낸다.
            saw.add(saw.remove(0));
        }
    }
}

반응형

댓글