모의 문제 - 특이한 자석

sycho·2024년 4월 9일
0

문제

https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AWIeV9sKkcoDFAVH

코드 (Java)

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


class Solution
{
	public static void main(String args[]) throws Exception
	{
//		System.setIn(new FileInputStream("res/input.txt"));

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		int T;
		T=Integer.parseInt(br.readLine().trim());
		int[][] magnets = new int[5][8];

		for(int test_case = 1; test_case <= T; test_case++)
		{
			int K = Integer.parseInt(br.readLine().trim());
			
			for (int magnet = 1; magnet <= 4; ++magnet) {
				StringTokenizer st = new StringTokenizer(br.readLine().trim());
				for (int blade = 0; blade < 8; ++blade) {
					magnets[magnet][blade] = Integer.parseInt(st.nextToken());
				}
			}
			
			int[] magnetTop = new int[5];
			int[] magnetR = new int[5];
			for (int i = 1; i < 4; ++i) {
				magnetR[i] = 2;
			}
			int[] magnetL = new int[5];
			for (int i = 2; i <= 4; ++i) {
				magnetL[i] = 6;
			}
			
//			for (int i = 1; i <= 4; ++i) {
//				for (int j = 0; j < 8; ++j) {
//					System.out.printf("%d ", magnets[i][j]);
//				}
//				System.out.printf("\n");
//			}
//			
			//simulation
			for (int move = 0; move < K; ++move) {
				StringTokenizer st = new StringTokenizer(br.readLine().trim());
				int num = Integer.parseInt(st.nextToken());
				int dir = Integer.parseInt(st.nextToken());
				
				//we change the top;
				magnetTop[num] = calcPos(magnetTop[num], dir);
				
				//we first check the right side.
				int tmpDir = dir;
				int tmpNum = num;
				while (tmpNum < 4) {
					int L = magnets[tmpNum+1][magnetL[tmpNum+1]];
					int R = magnets[tmpNum][magnetR[tmpNum]];
					magnetR[tmpNum] = calcPos(magnetR[tmpNum], tmpDir);
					if (L+R%2 == 1) { //different.
						magnetL[tmpNum+1] = calcPos(magnetL[tmpNum+1], -tmpDir);
						magnetTop[tmpNum+1] = calcPos(magnetTop[tmpNum+1], -tmpDir);
						tmpDir = -tmpDir;
						tmpNum++;
					} else {
						break;
					}
					
				}
				
				//we then check the left side.
				tmpDir = dir;
				tmpNum = num;
				while (tmpNum > 1) {
					int L = magnets[tmpNum][magnetL[tmpNum]];
					int R = magnets[tmpNum-1][magnetR[tmpNum-1]];
					magnetL[tmpNum] = calcPos(magnetL[tmpNum], tmpDir);
					if (L+R%2 == 1) { //different.
						magnetR[tmpNum-1] = calcPos(magnetR[tmpNum-1], -tmpDir);
						magnetTop[tmpNum-1] = calcPos(magnetTop[tmpNum-1], -tmpDir);
						tmpDir = -tmpDir;
						tmpNum--;
					} else {
						break;
					}
				}
//				
//				for (int i = 1; i <= 4; ++i) {
//					System.out.printf("magnet %d with top %d, left %d and right %d\n", i, magnetTop[i], magnetL[i], magnetR[i]);
//				}
				
			}
			
			//we check the top and calculate the score.
			int score = 0;
			for (int magnet = 1; magnet <= 4; ++magnet) {
				score += magnets[magnet][magnetTop[magnet]] << (magnet - 1);
			}
			
			bw.write("#" + test_case + " " + score + "\n");
		}
		bw.flush();
		bw.close();
	}
	
	public static int calcPos(int pos, int dir) {
		pos -= dir;
		if (pos >= 8) pos = 0;
		else if (pos < 0) pos = 7;
		return pos;
	}
}

풀이

  • 좀 요상한 시뮬레이션 문제.

  • 구현은 다음과 같이 했다.

    • 각 톱니별 top/left/right 부분 index를 지정했다.
      • 나중에 풀다보니 깨달은 점이 사실 top만 알아도 left/right는 역추적이 가능하긴 하다. 하지만 다른 태엽들의 회전 여부를 계산할 때 이전 위치를 가지고 고려하다보니 그렇게 좋은 방법은 아닌 것 같다.
    • top을 우선으로 갱신하며, left/right의 경우 맞붙은 태엽의 right/left랑 같이 회전 여부를 확인한다. 전자는 무조건 회전되고 후자는 상황에 따라 회전이 되거나 안된다. 후자가 회전이 된 경우 연쇄적으로 계속 추적.
    • 점수 계산 방식에서 shift 활용이 유용.
profile
안 흔하고 싶은 개발자. 관심 분야 : 임베디드/컴퓨터 시스템 및 아키텍처/웹/AI

0개의 댓글