백준🔗
14891번: 톱니바퀴
총 8개의 톱니를 가지고 있는 톱니바퀴 4개가 아래 그림과 같이 일렬로 놓여져 있다. 또, 톱니는 N극 또는 S극 중 하나를 나타내고 있다. 톱니바퀴에는 번호가 매겨져 있는데, 가장 왼쪽 톱니바퀴
www.acmicpc.net
문제
간단 풀이
오랜만에 구현 문제를 풀어봤다!!
문제를 읽어보니
(1) 회전 (톱니바퀴 상태 값들 전부 한 칸씩 이동시키기)
(2) 인덱스로 접근 (맞닿은 톱니바퀴 값 비교 & 마지막에 점수 계산)
이렇게 2가지 연산이 주로 필요해 보였다.
톱니바퀴 개수가 4개이고, 톱니바퀴 당 값이 8개씩이기 때문에 자료구조로 배열을 사용해도 1번이 O(8), 2번이 O(1)로 둘 다 상수 시간만큼 소요될 것이라고 생각했다. 리스트도 고려해 봤지만, 인덱스로 접근해서 값을비교할 일이 많은데 리스트는 O(1)이 아닌 그 이상이 소요되기 때문에 배열을 사용하기로 했다.
12시 방향을 0번 인덱스로 해서 시계 방향으로 돌면서 배열에 저장한다.
이 때 왼쪽 톱니바퀴의 2번 인덱스 값이 오른쪽 톱니바퀴의 6번 인덱스 값과 맞닿은 상태가 된다.
이 점을 이용해 4개의 톱니바퀴의 회전 방향 정보를 또 다른 1차원 배열로 관리하면서 톱니바퀴를 회전시키고 최종 점수를 구해줬다.
코드
import java.io.*;
import java.util.*;
public class Main {
static int[][] wheel;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
wheel = new int[5][8]; // 톱니바퀴 상태
for (int i = 1; i <= 4; i++) {
String input = br.readLine();
for (int j = 0; j < 8; j++) {
wheel[i][j] = input.charAt(j) - '0';
}
}
int K = Integer.parseInt(br.readLine()); // 회전 횟수
int[] turn = new int[5]; // 4개 톱니바퀴의 회전 방향 정보 저장할 배열
for (int k = 0; k < K; k++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int wheel_num = Integer.parseInt(st.nextToken());
int turn_dir = Integer.parseInt(st.nextToken());
Arrays.fill(turn, 0);
turn[wheel_num] = turn_dir;
// 왼쪽으로 가면서 톱니바퀴별 회전 방향 조사
for (int i = wheel_num; i > 1; i--) {
if (wheel[i][6] != wheel[i - 1][2]) { // 맞닿은 부분이 다른 경우
turn[i - 1] = turn[i] * (-1); // 반대 방향 회전
} else { // 맞닿은 부분이 같은 경우
break; // 이후로는 더이상 회전하지 않음
}
}
// 오른쪽으로 가면서 톱니바퀴별 회전 방향 조사
for (int i = wheel_num; i < 4; i++) {
if (wheel[i][2] != wheel[i + 1][6]) { // 맞닿은 부분이 다른 경우
turn[i + 1] = turn[i] * (-1); // 반대 방향 회전
} else {
break;
}
}
for (int i = 1; i <= 4; i++) {
if (turn[i] == 1) {
toRight(i);
continue;
}
if (turn[i] == -1) {
toLeft(i);
}
}
}
System.out.println(calScore());
}
// 시계방향 회전
static void toRight(int idx) {
int tmp = wheel[idx][7];
for (int i = 6; i >= 0; i--) {
wheel[idx][i + 1] = wheel[idx][i];
}
wheel[idx][0] = tmp;
}
// 반시계방향 회전
static void toLeft(int idx) {
int tmp = wheel[idx][0];
for (int i = 0; i < 7; i++) {
wheel[idx][i] = wheel[idx][i + 1];
}
wheel[idx][7] = tmp;
}
// 점수 계산
static int calScore() {
int res = 0;
int score = 1; // 획득 점수
for (int i = 1; i <= 4; i++) {
if (wheel[i][0] == 1) {
res += score;
}
score = score << 1; // 획득 점수 2배
}
return res;
}
}