본문 바로가기

숨막히는 알고말고/문제 풀이

[SWEA] 특이한 자석

👀 문제 설명

문제

로그인해야 문제를 볼 수 있다.

 

✍🏻풀이

4개의 자석의 정보를 저장하는 LinkedList 배열을 만들고 이를 사용해서 회전시키면 된다.

LinkedList<Integer>[] magnet은 각각의 4개의 자석 정보를 담는다.

magnet[0]은 1번 자석, magnet[1]은 2번 자석, magnet[2]는 3번, magnet[3]은 4번의 정보를 저장한다.

 

회전 시킬 자석과 방향을 입력받아 각각 standardNum과 rotateDir에 저장한다.

checkMagnets 메서드는 standardNum 자석을 회전시켰을 때, 다른 자석들이 회전하는지 확인해주는 메서드이다.

standardNum을 기준으로 오른쪽 자석들이 회전해야 하는지 확인할 때는, 기준 자석의 2번 자성 정보와 확인할 자석의 6번 자성 정보가 맞닿아있으므로, 그 두개를 비교한다.

왼쪽 자석들을 비교할 때는 기준 자석의 6번 자성 정보와 확인할 자석의 2번 자성 정보가 맞닿아있으므로, 그 둘을 비교한다.

이렇게 비교해서 자석들이 회전하는지 확인하고, 회전할 경우, queue에 { 자석 번호, 회전 방향 } 쌍으로 저장한다.

 

rotate 메서드는 queue에 저장된 회전할 자석들의 정보를 가져와서 각 자석들을 회전시켜주는 메서드이다.

각 자석의 자성 정보를 LinkedList를 사용해 저장했으므로,

시계 방향으로 회전할 때는 LinkedList의 맨 뒤의 값을 맨 앞으로 보내고,

반시계 방향으로 회전할 때는 LinkedList의 맨 앞의 값을 맨 뒤로 보내면 된다.

 

-> 만약 이렇게 queue에 회전할 것들을 저장해두지 않고, checkMagnets 안에서 바로바로 회전시킬 경우, 문제가 발생한다.

만약 2번 자석이 시계 방향으로 회전할 경우, 3번 자석은 기존의 2번 자석의 정보와 비교해야 하는데, 바뀐 2번의 자석과 비교하게 되기 때문에 제대로 비교가 되지 않는 문제가 발생한다.

 

코드

package swea;

// 특이한 자석 (https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AWIeV9sKkcoDFAVH&categoryId=AWIeV9sKkcoDFAVH&categoryType=CODE&problemTitle=%ED%8A%B9%EC%9D%B4%ED%95%9C+%EC%9E%90%EC%84%9D&orderBy=FIRST_REG_DATETIME&selectCodeLang=ALL&select-1=&pageSize=10&pageIndex=1 )

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

public class SWEA_4013 {
	
	private static int K;
	private static LinkedList<Integer>[] magnet;
	private static Queue<int[]> queue = new LinkedList<>();
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		StringTokenizer st;
		int T;

		T = Integer.parseInt(br.readLine());

		for (int tc = 1; tc <= T; tc++) {
			// input
			K = Integer.parseInt(br.readLine());
			magnet = new LinkedList[4];
			
			for (int m = 0; m < 4; m++) {
				magnet[m] = new LinkedList<>();
				
				st = new StringTokenizer(br.readLine());

				for (int b = 0; b < 8; b++) {
					magnet[m].add(Integer.parseInt(st.nextToken()));
				}
			}

			for (int k = 0; k < K; k++) {
				st = new StringTokenizer(br.readLine());
				int standardNum = Integer.parseInt(st.nextToken()) - 1; // 회전할 자석 번호
				int rotateDir = Integer.parseInt(st.nextToken()); // 회전 방향
				
				// solve
				checkMagnets(standardNum, rotateDir);
				while (!queue.isEmpty()) {
					int[] cur = queue.poll();
					
					rotate(cur[0], cur[1]);
				}
			}
			
			int ans = 0;
			for (int m = 0; m < 4; m++) {
				if (magnet[m].peekFirst() == 1) {
					ans += Math.pow(2, m);
				}
			}
			bw.write("#" + tc + " " + ans + "\n");
		}

		bw.flush();
		bw.close();
	}
	
	private static void checkMagnets(int standard, int dir) {
		queue.clear();
		queue.offer(new int[] { standard, dir });
		
		// 자석 번호를 기준으로 오른쪽 자석들을 회전해야 하는지 확인
		int before = standard;
		int beforeDir = dir; // 1은 시계 방향 회전, -1은 반시계 방향 회전, 0은 회전하지 않음
		for (int right = before + 1; right < 4; right++) {
			// before의 2번 자석과 right의 6번 자석 비교
			if (beforeDir != 0) { // 회전할 경우,
				if (magnet[before].get(2) == magnet[right].get(6)) { // 같은 극이라면, 회전하지 않음
					beforeDir = 0;
				}
				else { // 다른 극이라면, 회전
					if (beforeDir == 1) { // before이 시계 방향 회전이라면, right는 반시계 방향 회전
						beforeDir = -1;
					}
					else { // before이 반시계 방향 회전이라면, right는 시계 방향 회전
						beforeDir = 1;
					}
					queue.offer(new int[] { right, beforeDir });
				}
			}
			
			before = right;
		}
		
		// 왼쪽 자석들 확인
		before = standard;
		beforeDir = dir;
		for (int left = before - 1; left >= 0; left--) {
			// before의 6번 자석과 left의 2번 자석 비교
			if (beforeDir != 0) { // 회전할 경우,
				if (magnet[before].get(6) == magnet[left].get(2)) { // 같은 극이라면, 회전하지 않음
					beforeDir = 0;
				}
				else { // 다른 극이라면, 회전
					if (beforeDir == 1) { // before이 시계 방향 회전이라면, right는 반시계 방향 회전
						beforeDir = -1;
					}
					else { // before이 반시계 방향 회전이라면, right는 시계 방향 회전
						beforeDir = 1;
					}
					queue.offer(new int[] { left, beforeDir });
				}
			}
			
			before = left;
		}
	}
	
	private static void rotate(int magnetNum, int rotateDir) {
		if (rotateDir == 1) { // 시계 방향 회전
			// 맨 뒤 값이 맨 앞으로
			int last = magnet[magnetNum].pollLast();
			magnet[magnetNum].addFirst(last);
		}
		else { // 반시계 방향 회전
			// 맨 앞의 값이 맨 뒤로
			int first = magnet[magnetNum].pollFirst();
			magnet[magnetNum].addLast(first);
		}
	}

}

'숨막히는 알고말고 > 문제 풀이' 카테고리의 다른 글

[Baekjoon] 마법사 상어와 비바라기  (0) 2021.10.07
[Baekjoon] 모노미노도미노 2  (0) 2021.10.06
[SWEA] 최장 증가 부분 수열  (0) 2021.09.30
[SWEA] 탈주범 검거  (0) 2021.09.30
[SWEA] 보급로  (0) 2021.09.30