백준 14891번( 자바 )

Flash·2022년 1월 15일
0

BOJ-Algorithm

목록 보기
28/51
post-thumbnail

구현

백준 14891번 구현 문제를 Java로 풀어보았다.
조건이 여러 개라서 이 조건들을 모두 꼼꼼히 따져주는 작업이 필요하다. 중간에 빼먹어서 초반에 고생을 좀 했다.

문제가 역시 길기에 링크만 첨부한다.
https://www.acmicpc.net/problem/14891


톱니바퀴 클래스 만들기

톱니바퀴에 필요한 속성은 바퀴를 구성하고 있는 톱니 8개와 톱니바퀴 생성자 그리고 해당 바퀴를 회전시키는 메소드가 필요하다.
8개의 톱니를 표현하기 위해서는 회전시킬 경우를 고려해서 앞에 있는 원소를 맨 뒤에 보내기도 하고, 맨 뒤에 있는 원소를 맨 앞으로 보내기도 용이한 LinkedList를 이용했다.

아래는 톱니바퀴 클래스 코드다.

static class Wheel {
        LinkedList<Integer> teethes = new LinkedList<>();

        Wheel(String input){
            for(int i=0; i<8; i++)
                this.teethes.add(Character.getNumericValue(input.charAt(i)));
        }

        void rotate(int direction){
            if(direction==1){ // 시계 방향으로 돌릴 때
                int last = this.teethes.getLast();
                this.teethes.removeLast();
                this.teethes.addFirst(last);
            }
            else{ // 반시계 방향으로 돌릴 때
                int first = this.teethes.getFirst();
                this.teethes.removeFirst();
                this.teethes.addLast(first);
            }
        }
    }

어떤 톱니바퀴가 회전할까

맞닿아있는 톱니바퀴끼리 접촉 부분의 극성이 서로 다르면 회전이 가능하다. 이를 확인해주기 위한 메소드를 선언했다.
재귀방식을 통해 양 옆으로 뻗어나가도록 했다.

static int[] isRotatable = {0,0,0,0};

static void CheckRotatables(int startPoint, int direction){
        isRotatable[startPoint] = direction;
        int left = startPoint-1;    int right = startPoint+1;

        if(left>=0 && isRotatable[left]==0){
            if(wheels[startPoint].teethes.get(6)!=wheels[left].teethes.get(2))
                CheckRotatables(left, direction*-1);
        }
        if(right<4 && isRotatable[right]==0){
            if(wheels[startPoint].teethes.get(2)!=wheels[right].teethes.get(6))
                CheckRotatables(right, direction*-1);
        }
    }

이제 회전을 시켜주자

회전시킬 바퀴들을 모두 확인했다. 이제 네 개의 바퀴를 차례로 돌며 isRotatable의 정보에 따라 회전을 시켜주자.

static void Rotate(int whichWheel, int direction){
        CheckRotatables(whichWheel-1, direction);
        for(int i=0; i<4; i++){
            if(isRotatable[i]==0)   continue;
            else if(isRotatable[i]==1) wheels[i].rotate(1);
            else if(isRotatable[i]==-1) wheels[i].rotate(-1);
        }
        isRotatable = new int[4]; // 한 텀을 돌고나면 초기화해줘야 한다
    }

k번의 회전을 실행하자

위의 코드들을 모두 합쳐 k번의 회전을 돌리도록 for문을 작성하면 다음과 같다.

k = Integer.parseInt(bfr.readLine());
for(int i=0; i<k; i++){
    stk = new StringTokenizer(bfr.readLine());
    int whichWheel = Integer.parseInt(stk.nextToken());
    int direction = Integer.parseInt(stk.nextToken());
    Rotate(whichWheel, direction);
    }

아래는 내가 제출한 코드다.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.util.StringTokenizer;
import java.util.LinkedList;

public class boj14891 {
    static int k;
    static Wheel[] wheels = new Wheel[4];
    static int[] isRotatable = {0,0,0,0};

    public static void main(String args[]) throws IOException {
        BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer stk;
        for(int i=0; i<4; i++){
            String input = bfr.readLine();
            wheels[i] = new Wheel(input);
        }

        k = Integer.parseInt(bfr.readLine());
        for(int i=0; i<k; i++){
            stk = new StringTokenizer(bfr.readLine());
            int whichWheel = Integer.parseInt(stk.nextToken());
            int direction = Integer.parseInt(stk.nextToken());
            Rotate(whichWheel, direction);
        }

        bfw.write(String.valueOf(GetSum()));
        bfw.close();
    }

    static class Wheel {
        LinkedList<Integer> teethes = new LinkedList<>();

        Wheel(String input){
            for(int i=0; i<8; i++)
                this.teethes.add(Character.getNumericValue(input.charAt(i)));
        }

        void rotate(int direction){
            if(direction==1){ // 시계 방향으로 돌릴 때
                int last = this.teethes.getLast();
                this.teethes.removeLast();
                this.teethes.addFirst(last);
            }
            else{ // 반시계 방향으로 돌릴 때
                int first = this.teethes.getFirst();
                this.teethes.removeFirst();
                this.teethes.addLast(first);
            }
        }
    }

    static void Rotate(int whichWheel, int direction){
        CheckRotatables(whichWheel-1, direction);
        for(int i=0; i<4; i++){
            if(isRotatable[i]==0)   continue;
            else if(isRotatable[i]==1) wheels[i].rotate(1);
            else if(isRotatable[i]==-1) wheels[i].rotate(-1);
        }
        isRotatable = new int[4];
    }
    
    static void CheckRotatables(int startPoint, int direction){
        isRotatable[startPoint] = direction;
        int left = startPoint-1;    int right = startPoint+1;

        if(left>=0 && isRotatable[left]==0){
            if(wheels[startPoint].teethes.get(6)!=wheels[left].teethes.get(2))
                CheckRotatables(left, direction*-1);
        }
        if(right<4 && isRotatable[right]==0){
            if(wheels[startPoint].teethes.get(2)!=wheels[right].teethes.get(6))
                CheckRotatables(right, direction*-1);
        }
    }

    static int GetSum(){
        int answer = 0;
        if(wheels[0].teethes.get(0)==1) answer += 1;
        if(wheels[1].teethes.get(0)==1) answer += 2;
        if(wheels[2].teethes.get(0)==1) answer += 4;
        if(wheels[3].teethes.get(0)==1) answer += 8;
        return answer;
    }
}

profile
개발 빼고 다 하는 개발자

0개의 댓글