알고리즘 공부/구현 , 시뮬레이션

백준 14891 (톱니바퀴)

kdhoooon 2021. 4. 17. 14:39

www.acmicpc.net/problem/14891

 

14891번: 톱니바퀴

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

www.acmicpc.net

 

문제가 기니까 잘 읽고 이해해야한다.

 

풀이


같은 극이 맞닿은 톱니는 돌아가지 않고

다른 극이 맞닿은 톱니는 반대 방향으로 돈다.

 

이 두개의 조건이 핵심이다.

 

해당 기어의 번호 앞뒤로 반복문을 통해 기어를 돌리는 전형적인 시뮬레이션 문제다.

시뮬레이션 문제는 노하우는 있겠지만 구현을 시켜내면 되는 문제기 때문에 시간이 많이 걸리는 편이다.

 

n 번 톱니의 3번째 톱니와 n+1 번 톱니의 7번 톱니의 극이 같은지를 확인해서 돌려야한다.

 

static void moveGear(int gear_number, int direct) {
	
	int lastPole6 = (int) gear[gear_number].get(6);
	int lastPole2 = (int) gear[gear_number].get(2);
	spinGear(gear_number, direct);

	int direct_tmp = direct;
	for(int j = gear_number - 1; j >= 0 ; j--) {
		
		int tmp = (int) gear[j].get(6);
		
		//다른극 반대 방향
		if(lastPole6 != (int)gear[j].get(2)) {
			direct_tmp *= -1;
			spinGear(j, direct_tmp);
		}
		//같은 극 끝냄.
		else {
				break;
		}
		lastPole6 = tmp;
	}
	
	direct_tmp = direct;
	for(int j = gear_number + 1 ; j < 4 ; j++ ) {
		
		int tmp = (int) gear[j].get(2);
		//다른극 반대방향
		if(lastPole2 != (int)gear[j].get(6)) {
			direct_tmp *= -1;
			spinGear(j, direct_tmp);
		}
		//같은극 끝냄
		else
			break;
		
		lastPole2 = tmp;
	}
}

해당 기어의 앞뒤 기어들을 반복문으로 돌아가며 변하기 전의 기어 극을 저장해 놓고 다른극인지 같은극인지를 판단해서 방향을 돌려준다.

 

앞서 돌린 기어의 방향과 반대이므로 앞서 돌린 기어의 방향을 저장해 주어야한다.

 

톱니가 돌아가는 방식

 

시계방향의 경우

8번째 톱니가 12시방향에 오게된다. -> 리스트 제일 뒤의 톱니가 0번째 순서로 온다.

 

반시계방향의 경우

12시 방향의 톱니가 8번째 톱니가 된다. -> 0번째 톱니가 리스트 제일 뒤로 간다.

static void spinGear(int idx, int direct) {
	if(direct == 1) {
		int last = (int) gear[idx].remove(gear[idx].size() - 1);
		gear[idx].add(0, last);
	}
	else {
		int front = (int) gear[idx].remove(0);
		gear[idx].add(gear[idx].size(), front);
	}
}

 

 

<전체코드>

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

public class Main {	
	static StringBuilder sb = new StringBuilder();
	
	static List[] gear;
	
	public static void main(String[] args) throws IOException{
		
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
		
		gear = new List[4];
		for(int i = 0 ; i < 4 ; i++) {
			gear[i] = new ArrayList<Integer>();
		}
		
		for(int i = 0 ; i < 4 ; i++) {
			String[] pole = bufferedReader.readLine().split("");
			for(int j = 0 ; j < 8 ; j++) {
				gear[i].add(Integer.parseInt(pole[j]));
			}
		}
		
		int K = Integer.parseInt(bufferedReader.readLine());
		for(int i = 0 ; i < K ; i++) {
			StringTokenizer st = new StringTokenizer(bufferedReader.readLine());
			int gearNumber = Integer.parseInt(st.nextToken());
			int direct = Integer.parseInt(st.nextToken());
			
			moveGear(gearNumber -1, direct);
		}
		
		System.out.println(checkingPoint());
	}
	
	static int checkingPoint() {
		
		int point = 0;
		for(int i = 0 ; i < 4 ; i++) {
			if((int)gear[i].get(0) == 1) {
				point += Math.pow(2, i);
			}
		}
		
		return point;
	}
	
	static void moveGear(int gear_number, int direct) {
		

		int lastPole6 = (int) gear[gear_number].get(6);
		int lastPole2 = (int) gear[gear_number].get(2);
		spinGear(gear_number, direct);
		
		int direct_tmp = direct;
		for(int j = gear_number - 1; j >= 0 ; j--) {
			
			int tmp = (int) gear[j].get(6);
			
			//다른극 반대 방향
			if(lastPole6 != (int)gear[j].get(2)) {
				direct_tmp *= -1;
				spinGear(j, direct_tmp);
			}
			else {
				break;
			}
			lastPole6 = tmp;
		}
		
		direct_tmp = direct;
		for(int j = gear_number + 1 ; j < 4 ; j++ ) {
			
			int tmp = (int) gear[j].get(2);
			if(lastPole2 != (int)gear[j].get(6)) {
				direct_tmp *= -1;
				spinGear(j, direct_tmp);
			}
			else
				break;
			
			lastPole2 = tmp;
		}
	}
	
	static void spinGear(int idx, int direct) {
		if(direct == 1) {
			int last = (int) gear[idx].remove(gear[idx].size() - 1);
			gear[idx].add(0, last);
		}
		else {
			int front = (int) gear[idx].remove(0);
			gear[idx].add(gear[idx].size(), front);
		}
	}
	
}