다희의 코딩 성장일기

[백준] 15662. 톱니바퀴 (2) (자바 JAVA) 본문

Algorithm/백준 BOJ

[백준] 15662. 톱니바퀴 (2) (자바 JAVA)

ilmiodiario 2021. 8. 23. 16:03

[ 문제 ]  [백준] 15662. 톱니바퀴 (2) (자바 JAVA)

 

문제 링크 : https://www.acmicpc.net/problem/15662

 

15662번: 톱니바퀴 (2)

총 8개의 톱니를 가지고 있는 톱니바퀴 T개가 아래 그림과 같이 일렬로 놓여져 있다. 또, 톱니는 N극 또는 S극 중 하나를 나타내고 있다. 톱니바퀴에는 번호가 매겨져 있는데, 가장 왼쪽 톱니바퀴

www.acmicpc.net


# 접근 방법 및 풀이 

 

  • 톱니바퀴를 topni[][] 2차원 배열에 입력받는다.
  • 톱니바퀴끼리 서로 맞물린 곳의 극이 서로 달라 회전이 가능한지 체크하는 함수 check()
  • 회전시키는 함수 rotation()
  • 톱니바퀴 하나를 해당 방향(시계 or 반시계)으로 돌리는 함수 turn() 으로 3가지 함수를 구분해서 구현했다.
  • 먼저, check()함수는 boolean check[] 배열을 만들어 각 맞물린 톱니바퀴끼리 서로 다른지 확인해서 다르면 true를 해준다. 
  • 이때 check[] 배열의 크기는 톱니바퀴 갯수 T-1이다. 
  • 1-2 2-3 3-4
    T F T
  • 예를들어 T = 4 이면, 위와 같이 1번 2번 톱니바퀴 상태, 2번 3번  / 3번 4번 만 체크해주면 된다.
  • 톱니바퀴는 길이가 8이고, 톱니바퀴를 배열로 표시하면 다음과 같다. Topni[4][8]
  • 톱니 0 1 2 3 4 5 6 7
    1번 0 1 1 1 0 0 1 0
    2번 0 1 1 0 0 1 0 1
    3번 1 1 1 0 0 0 0 1
    4번 1 1 1 0 0 1 0 1
  • 따라서 check[]배열은 맞물려 있는 2번째와 6번째 idx를 비교하면 된다.
  • rotation() 함수는 먼저 돌려야 하는 해당 바퀴를 돌리고, 해당 바퀴 기준 왼쪽오른쪽을 나눠 순서대로 톱니바퀴를 회전시킨다.
  • 1 2 3 4 5 6
  • 예를들어, 3번 톱니바퀴를 회전시킨다면 3번을 먼저 회전시키고, 3번의 오른쪽인 4, 5, 6을 순서대로 회전시키고, 왼쪽인 2, 1을 순서대로 회전시킨다. 
  • 순서대로 회전시키는 이유는 5번,6번 톱니의 맞물린 곳이 N극과 S극으로 서로 달라 회전이 가능하다고 해도, 4번 톱니가 돌아야지만 5번 6번도 회전 가능하기 때문이다.
  •  turn() 함수는 d =1일 경우, 시계방향 d = -1일 경우 반시계방향으로 돌린다.
  • 그리고 위의 과정을 K번 반복하면 된다. 
  • 자세한건 코드참조

# 주의할 점 

 

  • 처음에 문제를 잘못 봐서 K번씩 돌리는 건 줄 알고 잘못 풀었다..한번 돌리는건데..
  • 로직 설계 빨리 했다고 해서 성급히 풀지말 것. 
  • 구현일 수록 변수를 잘 못 썻다거나, +1을 빼먹었다거나 > 등호를 잘못 썼다거나 그런 사소한 것에서 오류나니까 꼭 잘 확인하자!

 

JAVA 코드
package Silver;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class bj15662_톱니바퀴_2 {

	static int T, topni[][];
	static boolean check[];
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		T = Integer.parseInt(in.readLine());
		topni = new int[T][8];
		for (int i = 0; i < T; i++) {
			String s = in.readLine();
			for (int j = 0; j < 8; j++) {
				topni[i][j] = s.charAt(j) - '0';
			}
		}
		int K = Integer.parseInt(in.readLine());
		for (int i = 0; i < K; i++) {
			st = new StringTokenizer(in.readLine());
			int num = Integer.parseInt(st.nextToken())-1;
			int d = Integer.parseInt(st.nextToken());
			check = new boolean[T-1];
			check();
			rotation(num, d);
		}	
		int ans = 0;
		for (int i = 0; i < T; i++) {
			ans += topni[i][0];
		}
		System.out.println(ans);
	}
	private static void rotation(int num, int d) {
		turn(num, d);
		if(T > 1) {
			boolean turn[] = new boolean[T];
			turn[num] = true;
			//왼쪽
			int leftdir = d*-1;
			for (int i = num-1; i >= 0; i--) {
				if(check[i] && turn[i+1]) {
					turn[i] = true;
					turn(i, leftdir);
					leftdir *= -1;
				}
			}
			//오른쪽
			int rightdir = d*-1;
			for (int i = num+1; i < T; i++) {
				if(check[i-1] && turn[i-1]) {
					turn[i] = true;
					turn(i, rightdir);
					rightdir *= -1;
				}
			}
		}
	}

	private static void turn(int num, int d) {
		if(d == 1) {
			int tmp = topni[num][7];
			for (int i = 7; i > 0; i--) {
				topni[num][i] = topni[num][i-1];
			}
			topni[num][0] = tmp;
		}else {
			int tmp = topni[num][0];
			for (int i = 0; i < 7; i++) {
				topni[num][i] = topni[num][i+1];
			}
			topni[num][7] = tmp;
		}	
	}
	private static void check() {
		for (int i = 0; i < T-1; i++) {
			if(topni[i][2] != topni[i+1][6])
				check[i] = true;
		}
	}
}

 

 

 

REVIEW

구현은 진짜 다시 생각해도.. 변수 하나 어디서 이상하게 잘못 쓰면 삽질을 너무 많이 한다...

더 확실하게 실수하지 않고 푸는 연습이 중요하다.

Comments