IT recording...

[BOJ] 14891 톱니바퀴 - Java 본문

Algorithm

[BOJ] 14891 톱니바퀴 - Java

I-one 2022. 4. 8. 21:32

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

 

14891번: 톱니바퀴

첫째 줄에 1번 톱니바퀴의 상태, 둘째 줄에 2번 톱니바퀴의 상태, 셋째 줄에 3번 톱니바퀴의 상태, 넷째 줄에 4번 톱니바퀴의 상태가 주어진다. 상태는 8개의 정수로 이루어져 있고, 12시방향부터

www.acmicpc.net

 

[문제 풀이]

- 역시 삼성의 구현 문제 답게 별 알고리즘은 필요없고 문제 꼼꼼히 읽고 구현하는 문제

- 정말 별로다 너무 디버깅이 힘들다 ㅜㅜ

- 나는 톱니가 1,4번이면 각각 2번,3번만 체크하면 되고 2,3번이면 각각 1,3번, 2,4번을 체크해야 하는 것을 보고 재귀 짤바에야 톱니 4개밖에 없으니까 그냥 if문으로 각각 경우 다 해주는게 나을것같다고 생각했다.

- 근데 주의할점, 이렇게 로직이 비슷한 경우에는 복붙을 사용하게 되는데 변수 정말 꼼꼼하게 살펴보고 붙여넣자..

(이번에도 복붙하다가 숫자 안바꾼 것이 있어서 디버깅에 애 먹었다..)

 

- 배열을 옮길까 하다가 그러면 시간초과 날 것 같아서 인덱스를 관리하기로 했다.

 (근데 너무 복잡하다.)

- 시계방향으로 돌렸다면 원래 index1자리에 있던 것이 2로 이동한다.

  내가 시계방향(1)으로 돌린 후 N번 자리에 있는 값을 얻고자 한다. 그러면 그 값은 8에서 온 값이기 때문에 , 원래 톱니의 N-1 을 찾아야 한다. 

예를 들면 시계방향(1)으로 돌린 후 3번 자리에 있는 값을 얻고자 하면, 3-1=2, 즉 원래 톱니의 2번째 값을 취하면 된다.

원래 톱니 1 2 3 4 5 6 7 8
시계방향 (sawDir) 8 1 2 3 4 5 6 7
반시계방향 (sawDir) 2 3 4 5 6 7 8 1

- 그래서 sawDir이라는 배열을 만들어 시계방향으로 회전하면 -1을 더하고, 반시계방향으로 회전하면 1을 더한다. (왜 반대인지 이해가 안간다면 표를 다시 살펴보자. 시계방향으로 돈 후 3번 자리에 있는 2는 원래 2번 자리에 있던 애였다. 그래서 이 2를 얻기 위해 -1을 하는 것이다.)

- 그리고 M번째 톱니바퀴의 N번 자리에 있는 값을 얻고자 할 때 N+sawDir[M] 을 통해 원하는 값을 얻으면 된다.

 

[코드]

import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Boj14891_톱니바퀴 {
    static StringTokenizer st;
    static int K;
    static int[][] Saw = new int[4+1][8+1]; //Saw[i][j] : 톱니바퀴 i번째의 j번째 톱니
    static int[] sawDir = new int [4+1];
    static int answer;

    public static void main(String[] args) throws Exception{
        System.setIn(new FileInputStream("src/main/java/input.txt"));
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        for(int i=1;i<5;i++){
            String string = br.readLine();
            for(int j=0;j<string.length();j++){
                Saw[i][j+1] = Integer.parseInt(String.valueOf(string.charAt(j)));
            }
        }
        K = Integer.parseInt(br.readLine());

        //==========
        for(int i=0;i<K;i++){
            st = new StringTokenizer(br.readLine());
            int sawNum = Integer.parseInt(st.nextToken()); //0:N극, 1:S극
            int dir = Integer.parseInt(st.nextToken()); //1:시계방향 , -1:반시계방향

            //바뀌기 전에 비교 후 1,2,3,4 각각 무슨 방향으로 돌지 확인해야함 -> sawDir[i] 설정
            int one_3 = getPos(1,3+sawDir[1]);
            int one_7 = getPos(1,7+sawDir[1]); //사실 필요없음
            int two_3 = getPos(2,3+sawDir[2]);
            int two_7 = getPos(2,7+sawDir[2]);
            int three_3 = getPos(3,3+sawDir[3]);
            int three_7 = getPos(3,7+sawDir[3]);
            int four_3 = getPos(4,3+sawDir[4]); //사실 필요없음
            int four_7 = getPos(4,7+sawDir[4]);

            if(sawNum == 1){ //톱니바퀴 1번
                sawDir[1] += dir * (-1);
                if(one_3 != two_7){ //둘이 다르면 방향 바꾸기
                    dir *= -1;
                }
                else{
                    dir = 0; //같으면 그 이후로 안움직임
                }
                sawDir[2] += dir * (-1);
                if(two_3 != three_7){
                    dir *= -1;
                }
                else{
                    dir = 0;
                }
                sawDir[3] += dir * (-1);
                if(three_3 != four_7){
                    dir *= -1;
                }
                else{
                    dir = 0;
                }
                sawDir[4] += dir * (-1);
            }
            //2 -> 1 , 2 -> 3 -> 4
            else if(sawNum == 2){
                sawDir[2] += dir * (-1); //시계방향이면 -1, 반시계방향이면 1을 더함
                
                //2 -> 1
                int twoToOne = 0;
                if(one_3 != two_7){ //둘이 다르면 방향 바꾸기
                    twoToOne = dir * -1;
                }
                sawDir[1] += twoToOne * (-1);

                //2 -> 3 -> 4
                if(two_3 != three_7){
                    dir *= -1;
                }
                else{ //같으면 그 이후로 안움직임
                    dir = 0;
                }
                sawDir[3] += dir * (-1);
                if(three_3 != four_7){
                    dir *= -1;
                }
                else{
                    dir = 0;
                }
                sawDir[4] += dir * (-1);
            }
            //3 -> 2 -> 1 , 3 -> 4
            else if(sawNum == 3){
                sawDir[3] += dir * (-1); //시계방향이면 -1, 반시계방향이면 1을 더함

                //3 -> 4
                int threeToFour = 0;
                if(three_3 != four_7){
                    threeToFour = dir * -1;
                }
                sawDir[4] += threeToFour * (-1);

                //3 -> 2 -> 1
                if(two_3 != three_7){ //둘이 다르면 방향 바꾸기
                    dir *= -1;
                }
                else{ //같으면 그 이후로 안움직임
                    dir = 0;
                }
                sawDir[2] += dir * (-1);
                if(one_3 != two_7){ 
                    dir *= -1;
                }
                else{
                    dir = 0;
                }
                sawDir[1] += dir * (-1);
            }
            //4 -> 3 -> 2 -> 1
            else{
                sawDir[4] += dir * (-1); //시계방향이면 -1, 반시계방향이면 1을 더함
                if(three_3 != four_7){
                    dir *= -1;
                }
                else{
                    dir = 0;
                }
                sawDir[3] += dir * (-1);
                if(two_3 != three_7){
                    dir *= -1;
                }
                else{
                    dir = 0;
                }
                sawDir[2] += dir * (-1);
                if(one_3 != two_7){ //둘이 다르면 방향 바꾸기
                    dir *= -1;
                }
                else{
                    dir = 0;
                }
                sawDir[1] += dir * (-1);
            }
        }
        //다 돌림, 점수 계산 고고
        getScore();
        System.out.println(answer);
    }

    static void getScore(){
        for(int i=1;i<5;i++){
            int value = getPos(i,1+sawDir[i]); //1(12시방향)에 있는 값
            if(value==1){ //S극이면
                answer += Math.pow(2,i-1);
            }
        }
    }

    static int getPos(int sawNum, int p){
        int pos = p % 8;
        if(pos == 0){ //나머지가 0이면 8로
            pos = 8;
        }
        else if(pos < 0){ //나머지가 음수면 ex) 나머지가 -1이면 7이 나와야 한다.
            pos *= -1;
            pos = 8 - pos;
        }
        return Saw[sawNum][pos]; //Saw의 pos1칸을 확인하면 값을 얻을 수 있음
    }
}

[풀이 시간]

3h 정도 걸렸다.

디버깅이 너무 오래걸린다. 하나라도 잘못 짜면 디버깅만 한세월.. 

조건을 충분히 검토하고, 로직 짠 후에 키보드 잡는 연습하자

'Algorithm' 카테고리의 다른 글

[BOJ] 14889 스타트와링크 - Java  (0) 2022.04.13
[BOJ] 15683 감시 - Java  (0) 2022.04.12
[BOJ] 14890 경사로 - Java  (0) 2022.04.08
[PG] 정수삼각형 - Java  (0) 2022.03.29
[PG] 전화번호목록 - Java  (0) 2022.03.28
Comments