[백준 14891번 ]톱니바퀴

ynoolee·2022년 3월 7일
0

코테준비

목록 보기
117/146

[백준 14891번 ]톱니바퀴

14891번: 톱니바퀴

  • 12시 방향부터, 시계방향 순서대로 주어진다. N(0), S(1)
  • 회전시킨 톱니바퀴 번호, 회전시킨 방향
    • 1 : 시계방향, -1은 반시계방향
  • 상태는 8개의 정수로 주어진다. 12시방향부터 시계방향 순서대로.
시계방향으로 회전하게 되면, 
가장 뒤에 있는 수를 빼와서 맨 앞에 붙여주도록 한다 
시계 반대 방향으로 회전하게 되면
가장 앞에 있는 수를 빼서 맨 뒤에 붙여주도록 한다. 

LinkedList를 사용해야할텐데, 이를 사용하면, 다른 톱니와 맞다아있는(2번째,6번째 톱니는 매번 계산해내야한다)

톱니의 개수가 4개로 제한 && k가 100이기 때문에, 매 번 계산을 해도 괜찮을 듯 하다.
실제 자료구조를 사용할지
비트마스크를 사용할지 고민했다
최종적으로는 원형 큐를 사용했다 ( JAVA에서 비트마스크 사용...끔찍한 도전이었다.그래도 풀리긴 했다. C++이 좋은듯)

문제풀이

  • 톱니는 한 칸 회전한다.
  • 맞닿은 극이 같으면 회전하지 않는다.
  • 맞닿은 극이 다르면 “반대 방향”으로 회전한다.
    • 맞닿는 칸 : 각 톱니가 0 ~ 7번이라 하면, 2번과 6번이 맞닿는 톱니라는 사실을 생각하자.

circular 큐 처럼 풀이했다. ( 회전을 하는 것이지 수가 바뀌는 건 아니니까 )

start를 두고

  • 시계방향 :
    • 이 때 주의할 것 : start < 0 이 되면 7로 세팅 해줄것
    (start--) % 8
  • 반시계방향:
    (start++) % 8

맞닿은 애들을 구해야하는데 이는

(start+2)%8
(start+6)%8

1,2,3,4 번 톱니들을 관리해줘야한다.

  • 1번 rotate → 2번 움직일 수 있음
  • 2 → 1,3
  • 3 → 2,4
  • 4 → 1

이 때, 이미 이 차례에서 한 번 rotate한 톱니는 다시 rotate하지 않아야함.

황당한 실수를 하고 있었다

switch - case에서 break; 문을 안 달아서 다른 case까지 들어갔다 나오고 있었음...;;

import java.io.*;
import java.util.*;

public class Main {
    public static final int TOOTH_CNT = 8;
    public static String[] tops = new String[4]; // 4개의 톱니바퀴들
    public static int[] starts = new int[4]; // 각 톱니들의 start index
    public static boolean[] visit = new boolean[4]; // 각 톱니바퀴의 회전여부

    public static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    public static StringTokenizer st;
    public static void setting() throws IOException {
        for(int i =0 ;i<4;i++){
            tops[i] = br.readLine();
        }
        int cnt = Integer.parseInt(br.readLine()); // 회전 횟수
        int rot = 0;
        for(int i = 0 ;i <cnt;i++){
            // 회전시킬 때 마다, 각 톱니의 회전 여부를 초기화시킨다
            Arrays.fill(visit, false);
            // 회전
            st = new StringTokenizer(br.readLine());
            rot = Integer.parseInt(st.nextToken()) - 1; // 회전시키는 톱니번호
            if(st.nextToken().equals("-1")) counterClockWise(rot);
            else clockWise(rot);
        }

    }
    public static int solve(){
        int sum = 0;
        int val = 1;
        for(int i = 0 ;i < 4; i++){
            if (tops[i].charAt(starts[i]) == '0') continue;
            sum += Math.pow(2,i);

        }
        return sum;
    }
    // top 번 톱니의 idx 에 위치한 글자 : '0' 또는 '1'
    public static char get(int top,int idx){
        // starts[top] 은 현재 top 번 톱니의 start
        return tops[top].charAt((starts[top] + idx) % TOOTH_CNT );
    }

    // top 번 톱니를 시계방향 회전
    public static void clockWise(int top){
        if (visit[top]) return;
        visit[top] = true;
        switch (top){
            case 0:
                if ( get(top,2) != get(1,6) ) counterClockWise(1);
                break;
            case 1:
                if ( get(top,2) != get(2,6) ) counterClockWise(2);
                if ( get(top,6) != get(0,2) ) counterClockWise(0);
                break;
            case 2:
                if ( get(top,2) != get(3,6) ) counterClockWise(3);
                if ( get(top,6) != get(1,2) ) counterClockWise(1);
                break;
            case 3:
                if ( get(top,6) != get(2,2) ) counterClockWise(2);
        }
        starts[top] = (starts[top] - 1 < 0 ? 7 : starts[top] - 1 ) % TOOTH_CNT;
    }
    public static void counterClockWise(int top){
        if (visit[top]) return;
        visit[top] = true;
        switch (top){
            case 0:
                if ( get(top,2) != get(1,6) ) clockWise(1);
                break;
            case 1:
                if ( get(top,2) != get(2,6) ) clockWise(2);
                if ( get(top,6) != get(0,2) ) clockWise(0);
                break;
            case 2:
                if ( get(top,2) != get(3,6) ) clockWise(3);
                if ( get(top,6) != get(1,2) ) clockWise(1);
                break;
            case 3:
                if ( get(top,6) != get(2,2) ) clockWise(2);
        }
        starts[top] = (starts[top] + 1) % TOOTH_CNT;
    }

    public static void main(String[] args)throws IOException {
        setting();
        System.out.println(solve());
    }

}

0개의 댓글