(JAVA) 4013. [모의 SW 역량테스트] 특이한 자석

Standard

문제 링크: https://www.swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AWIeV9sKkcoDFAVH&

이론적으로는 BFS로 구성할 수 있을 것 같긴 한데… 그냥 나름대로 풀이함.
– 각 자석 별로 arrowIdx (화살표 부분), leftIdx (왼쪽 부분), rightIdx (오른쪽 부분)가 있음.
회전할 때 세 값을 모두 업데이트 해야됨 (주의점: 반시계 방향이면 arrowIdx 가 증가하고, 시계 방향이면 arrowIdx가 감소함)
– 최초로 회전하는 자석 (trigger)을 기준으로 오른쪽 방향으로 연쇄적 처리, 왼쪽 방향으로 연쇄적 처리함
(최초 회전한 자석 기준으로 오른쪽 자석이 영향을 받고, 그 오른쪽 자석이 영향을 받고… 이런 방식.
역으로 왼쪽 좌석이 영향을 받고, 그 인쪽 좌석이 영향을 받고… 이런 식)
– 회전하는 자석 기준으로 회전 가능한 방향을 계속 swap (1->-1->1->…)하면서 업데이트
– 연쇄적으로 처리할 때, 직전 자석 (왼쪽으로 갈 때는 자기 오른쪽, 오른쪽으로 갈 때는 자기 왼쪽)과 현재 자석이 맞닿은 두 극이 다를 때만 회전 가능으로 처리 (이외의 경우 회전하지 않음)
직전 좌석이 회전하지 않으면 무조건 현재 자석은 회전하지 않도록 함
– 지정한 만큼 자석이 회전되고 나면, 점수를 구함.

import java.io.*;

public class Solution {
	public static final int numMagnetic = 4;
	public static final int numTooth = 8;
	
	public static void main(String[] args) throws IOException {
		//System.setIn(new FileInputStream("./src/sample_input.txt"));
		
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
		
		try {
			int numCases = Integer.parseInt(reader.readLine());
	
			for (int num = 0; num < numCases; num++) {
				writer.write("#" + String.valueOf(num + 1) + " ");
				
				int numK = Integer.parseInt(reader.readLine()); // 회전 케이스 갯수 
				int[][] magneticInfo = new int[numMagnetic][numTooth]; // idx1: 0~3 (n번째 자석) / idx2: 0~7 (n번째 날) / N극: 0, S극: 1
				int[] arrowIdx = new int[numMagnetic]; // 화살표 idx / idx1: 0~3 (n번째 자석) / 0~7 (n번째 날)
				int[] leftIdx = new int[numMagnetic]; // 맨 왼쪽 부분 idx / idx1: 0~3 (n번째 자석) / 0~7 (n번째 날)
				int[] rightIdx = new int[numMagnetic]; // 맨 오른쪽 부분 idx / idx1: 0~3 (n번째 자석) / 0~7 (n번째 날)
								
				// 자석 map 만들기
				for (int i = 0; i < numMagnetic; i++) {
					String[] tmp = reader.readLine().split(" ");
					
					for (int j = 0; j < tmp.length; j++) 
						magneticInfo[i][j] = Integer.parseInt(tmp[j]);
					
					leftIdx[i] = 6; // -2, +8 하면 6과 동일 
					rightIdx[i] = 2;// +2
				}
				
				boolean[] willRotate = new boolean[numMagnetic]; // 실제 회전 여부 (true: 회전, false: 비회전)
				int[] rotateDirection = new int[numMagnetic]; // -1: 반시계 (왼쪽), 1: 시계 (오른쪽)
				
				// 실제 회전 처리 
				for (int i = 0; i < numK; i++) {
					String[] tmp_ = reader.readLine().split(" ");
					int triggerIdx = Integer.parseInt(tmp_[0]) - 1; // 1~4번째로 되어있으므로 0~3으로 수정
					
					for (int j = 0; j < numMagnetic; j++) {
						willRotate[j] = false;
					}
					
					// 직접 돌리는 자석은 무조건 회전됨
					willRotate[triggerIdx] = true;
					rotateDirection[triggerIdx] = Integer.parseInt(tmp_[1]);
					
					// 현재 자석 기준 오른쪽 처리
					for (int j = triggerIdx + 1; j < numMagnetic; j++) {
						// 왼쪽 자석이 회전하고, 왼쪽 자석 오른극과 지금 자석 왼극이 다른 경우 회전 정보 갱신
						if (willRotate[j - 1] == true && magneticInfo[j - 1][rightIdx[j - 1]] != magneticInfo[j][leftIdx[j]]) {
							willRotate[j] = true;
						}
						rotateDirection[j] = -rotateDirection[j - 1]; // 반대로 회전
					}
					
					// 현재 자석 기준 왼쪽 처리
					for (int j = triggerIdx - 1; j >= 0; j--) {
						// 오른쪽 자석이 회전하고, 오른쪽 자석 왼극과 지금 자석 오른극이 다른 경우 회전 정보 갱신
						if (willRotate[j + 1] == true && magneticInfo[j + 1][leftIdx[j + 1]] != magneticInfo[j][rightIdx[j]]) {
							willRotate[j] = true;
						}
						rotateDirection[j] = -rotateDirection[j + 1]; // 반대로 회전
					}

					// 회전 후 정보 처리
					for (int j = 0; j < numMagnetic; j++) {
						if (willRotate[j] == true) {
							switch (rotateDirection[j]) {
							case -1: // 반시계
								arrowIdx[j]++;
								leftIdx[j]++;
								rightIdx[j]++;
								
								arrowIdx[j] %= numTooth;
								leftIdx[j] %= numTooth;
								rightIdx[j] %= numTooth;

								break;
							case 1: // 시계
								arrowIdx[j]--;
								leftIdx[j]--;
								rightIdx[j]--;
								
								if (arrowIdx[j] < 0)
									arrowIdx[j] += numTooth;
								if (leftIdx[j] < 0)
									leftIdx[j] += numTooth;
								if (rightIdx[j] < 0)
									rightIdx[j] += numTooth;
								
								break;
							}
						}
					}
					
				}

				int answer = 0;
				for (int i = 0; i < numMagnetic; i++) {
					// 각 화살표 부분의 값이 S극일 경우 점수 더함  
					if (magneticInfo[i][arrowIdx[i]] == 1)
						answer += 1 << i;
				}
				writer.write(answer + System.lineSeparator());
				writer.flush();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.