본문 바로가기
Problem Solving/삼성 SW 역량 테스트 기출

백준 5373 : 큐빙

by Libi 2021. 8. 2.
반응형

https://www.acmicpc.net/problem/5373

 

5373번: 큐빙

각 테스트 케이스에 대해서 큐브를 모두 돌린 후의 윗 면의 색상을 출력한다. 첫 번째 줄에는 뒷 면과 접하는 칸의 색을 출력하고, 두 번째, 세 번째 줄은 순서대로 출력하면 된다. 흰색은 w, 노란

www.acmicpc.net

[ 문제풀이 ]

지금까지 풀어본 삼성 SW 역량 테스트 기출문제들 중 가장 시간이 많이 걸린 문제이다. 단순한 시뮬레이션 문제이지만 완전 하드코딩 문제이기 때문에 디버깅하기도 어려웠고 그냥 빡셌던 문제인 것 같다.

1. 큐빙을 3차원이 아닌 아래와 같이 2차원 도면으로 표현한다면 구현하기가 조금 쉬울 것이다.

          1  2  3               
          4  5  6 
          7  8  9                         
10 11 12 13 14 15 16 17 18 19 20 21                        뒤(B)
22 23 24 25 26 27 28 29 30 31 32 33              왼쪽(L) 아래(D) 오른쪽(R) 윗(U)
34 35 36 37 38 39 40 41 42 43 44 45                        앞(R)
         46 47 48
         49 50 51
         52 53 54

2. 시계/반시계 방향으로 회전하는 함수 2개를 구현하지 말고 한 방향으로 통일하자. 반시계 방향은 결국 시계방향으로 3번 회전한 것이기 때문에 한 방향으로 통일할 수 있다. 큐브를 돌리는 횟수인 n이 최대 1000이기 때문에 3번 회전한다고 해서 시간 초과가 나지는 않을 것이다.

3. 큐빙을 나와 같은 2차원 도면으로 표현했을 경우 회전시킬 면을 정면으로 두고 시계방향으로 회전시키기 때문에 회전시킨 후 다시 2차원 배열로 값을 옮길 때 방향에 따라 상/하 or 좌/우를 반전시켜줘야 한다. 이것은 머리로 한 번 2차원 도면을 3차원 형태로 접어본다면 무슨 뜻인지 이해할 수 있을 것이다.

 

문제가 상당히 더럽지만 공간지각 능력이 뛰어나다면 그나마 수월하게? 해결할 수 있을 것이다.

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;

public class Main {

	static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
	static StringTokenizer st;
	
	static char[][] init = {{' ', ' ', ' ', 'o', 'o', 'o', ' ', ' ', ' ', ' ', ' ', ' '},
							{' ', ' ', ' ', 'o', 'o', 'o', ' ', ' ', ' ', ' ', ' ', ' '},
							{' ', ' ', ' ', 'o', 'o', 'o', ' ', ' ', ' ', ' ', ' ', ' '},
							{'g', 'g', 'g', 'y', 'y', 'y', 'b', 'b', 'b', 'w', 'w', 'w'},
							{'g', 'g', 'g', 'y', 'y', 'y', 'b', 'b', 'b', 'w', 'w', 'w'},
							{'g', 'g', 'g', 'y', 'y', 'y', 'b', 'b', 'b', 'w', 'w', 'w'},
							{' ', ' ', ' ', 'r', 'r', 'r', ' ', ' ', ' ', ' ', ' ', ' '},
							{' ', ' ', ' ', 'r', 'r', 'r', ' ', ' ', ' ', ' ', ' ', ' '},
							{' ', ' ', ' ', 'r', 'r', 'r', ' ', ' ', ' ', ' ', ' ', ' '}};
	
//	static int[][] init = {{0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0},
//						   {0, 0, 0, 4, 5, 6, 0, 0, 0, 0, 0, 0},
//						   {0, 0, 0, 7, 8, 9, 0, 0, 0, 0, 0, 0},
//						   {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21},
//						   {22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33},
//						   {34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45},
//						   {0, 0, 0, 46, 47, 48, 0, 0, 0, 0, 0, 0},
//						   {0, 0, 0, 49, 50, 51, 0, 0, 0, 0, 0, 0},
//						   {0, 0, 0, 52, 53, 54, 0, 0, 0, 0, 0, 0},};

	static char[][] cube, temp;

	public static void main(String[] args) throws IOException {
		cube = new char[9][12];
		temp = new char[9][12];

		int testCase = Integer.parseInt(br.readLine());
		
		while (testCase-- > 0) {
			int n = Integer.parseInt(br.readLine());
			st = new StringTokenizer(br.readLine());
			initCube();//cube 초기화
			
			for (int i = 0; i < n; ++i) {
				String cmd = st.nextToken();

				//반시계 방향을 시계 방향으로 통일
				if (cmd.charAt(1) == '-')simulation(cmd.charAt(0), 3);
				else simulation(cmd.charAt(0), 1);

				initTemp();//temp 초기화
			}
			printUp();
		}
		bw.flush();bw.close();br.close();
	}

	public static void initCube() {
		for (int i = 0; i < 9; ++i) {
			for (int j = 0; j < 12; ++j) {
				cube[i][j] = init[i][j];
			}
		}
	}

	public static void initTemp() {
		for (int i = 0; i < 9; ++i) {
			for (int j = 0; j < 12; ++j) {
				temp[i][j] = '\0';
			}
		}
	}

	public static void simulation(char cmd, int count) {
		if (cmd == 'U') {
			for (int i = 0; i < count; ++i) {
				//뒷 면
				temp[0][3] = cube[5][0];
				temp[0][4] = cube[4][0];
				temp[0][5] = cube[3][0];

				//왼쪽 면
				temp[3][0] = cube[8][3];
				temp[4][0] = cube[8][4];
				temp[5][0] = cube[8][5];

				//앞 면
				temp[8][3] = cube[5][8];
				temp[8][4] = cube[4][8];
				temp[8][5] = cube[3][8];

				//오른쪽 면
				temp[5][8] = cube[0][5];
				temp[4][8] = cube[0][4];
				temp[3][8] = cube[0][3];

				//윗 면
				reverseLeftAndRight(3, 9);
				rotation(3, 9);
				copyCube();
				reverseLeftAndRight(3, 9);
			}
		} else if (cmd == 'D') {
			for (int i = 0; i < count; ++i) {
				//뒷 면
				temp[2][3] = cube[3][6];
				temp[2][4] = cube[4][6];
				temp[2][5] = cube[5][6];

				//왼쪽 면
				temp[3][2] = cube[2][5];
				temp[4][2] = cube[2][4];
				temp[5][2] = cube[2][3];

				//앞 면
				temp[6][3] = cube[3][2];
				temp[6][4] = cube[4][2];
				temp[6][5] = cube[5][2];

				//오른쪽 면
				temp[5][6] = cube[6][3];
				temp[4][6] = cube[6][4];
				temp[3][6] = cube[6][5];

				//아랫 면
				reverseLeftAndRight(3, 3);
				rotation(3, 3);
				copyCube();
				reverseLeftAndRight(3, 3);
			}
		} else if (cmd == 'F') {
			for (int i = 0; i < count; ++i) {
				//아랫 면
				temp[5][3] = cube[5][6];
				temp[5][4] = cube[5][7];
				temp[5][5] = cube[5][8];

				//오른쪽 면
				temp[5][6] = cube[5][9];
				temp[5][7] = cube[5][10];
				temp[5][8] = cube[5][11];

				//윗 면
				temp[5][11] = cube[5][2];
				temp[5][10] = cube[5][1];
				temp[5][9] = cube[5][0];

				//왼쪽 면
				temp[5][2] = cube[5][5];
				temp[5][1] = cube[5][4];
				temp[5][0] = cube[5][3];

				//앞 면
				reverseUpAndDown(6, 3);
				rotation(6, 3);
				copyCube();
				reverseUpAndDown(6, 3);
			}
		} else if (cmd == 'B') {
			for (int i = 0; i < count; ++i) {
				//아랫 면
				temp[3][3] = cube[3][0];
				temp[3][4] = cube[3][1];
				temp[3][5] = cube[3][2];

				//오른쪽 면
				temp[3][6] = cube[3][3];
				temp[3][7] = cube[3][4];
				temp[3][8] = cube[3][5];

				//윗 면
				temp[3][9] = cube[3][6];
				temp[3][10] = cube[3][7];
				temp[3][11] = cube[3][8];

				//왼쪽 면
				temp[3][2] = cube[3][11];
				temp[3][1] = cube[3][10];
				temp[3][0] = cube[3][9];

				//뒷 면
				reverseUpAndDown(0, 3);
				rotation(0, 3);
				copyCube();
				reverseUpAndDown(0, 3);
			}
		} else if (cmd == 'L') {
			for (int i = 0; i < count; ++i) {
				//윗 면
				temp[3][11] = cube[2][3];
				temp[4][11] = cube[1][3];
				temp[5][11] = cube[0][3];

				//앞 면
				temp[6][3] = cube[5][11];
				temp[7][3] = cube[4][11];
				temp[8][3] = cube[3][11];

				//아랫 면
				temp[3][3] = cube[6][3];
				temp[4][3] = cube[7][3];
				temp[5][3] = cube[8][3];

				//뒷 면
				temp[2][3] = cube[5][3];
				temp[1][3] = cube[4][3];
				temp[0][3] = cube[3][3];

				//왼쪽 면
				reverseLeftAndRight(3, 0);
				rotation(3, 0);
				copyCube();
				reverseLeftAndRight(3, 0);
			}
		} else if (cmd == 'R') {
			for (int i = 0; i < count; ++i) {
				//아랫 면
				temp[3][5] = cube[0][5];
				temp[4][5] = cube[1][5];
				temp[5][5] = cube[2][5];

				//앞 면
				temp[6][5] = cube[3][5];
				temp[7][5] = cube[4][5];
				temp[8][5] = cube[5][5];

				//윗 면
				temp[3][9] = cube[8][5];
				temp[4][9] = cube[7][5];
				temp[5][9] = cube[6][5];

				//뒷 면
				temp[0][5] = cube[5][9];
				temp[1][5] = cube[4][9];
				temp[2][5] = cube[3][9];

				//오른쪽 면
				reverseLeftAndRight(3, 6);
				rotation(3, 6);
				copyCube();
				reverseLeftAndRight(3, 6);
			}
		}
	}

	//시계 방향으로 90도 회전
	public static void rotation(int sy, int sx) {
		for (int i = sy, k = sx + 2; i < sy + 3; ++i, --k) {
			for (int j = sx, t = 0; j < sx + 3; ++j, ++t) {
				temp[sy + t][k] = cube[i][j];
			}
		}
	}

	//cube의 좌우 변경
	public static void reverseLeftAndRight(int sy, int sx) {
		char ret = '\0';
		for (int i = sy; i < sy + 3; ++i) {
			ret = cube[i][sx];
			cube[i][sx] = cube[i][sx + 2];
			cube[i][sx + 2] = ret;
		}
	}

	//cube의 상하 변경
	public static void reverseUpAndDown(int sy, int sx) {
		char ret = '\0';
		for (int i = sx; i < sx + 3; ++i) {
			ret = cube[sy][i];
			cube[sy][i] = cube[sy + 2][i];
			cube[sy + 2][i] = ret;
		}
	}

	//temp -> cube
	public static void copyCube() {
		for (int i = 0; i < 9; ++i) {
			for (int j = 0; j < 12; ++j) {
				if (temp[i][j] == '\0') continue;
				cube[i][j] = temp[i][j];
			}
		}
	}

	//윗면 출력
	public static void printUp() throws IOException {
		for (int i = 3; i < 6; ++i) {
			for (int j = 11; j > 8; --j) {
				bw.write(cube[i][j]);
			}bw.write("\n");
		}
	}
}

 

 

반응형

댓글