[백준 Platinum V] 큐빙 - 5373 (C++)

yeonjuLee·2025년 4월 7일

코딩테스트 대비

목록 보기
20/32

오늘의 학습 키워드

  • 시뮬레이션
  • 삼성기출

[백준] 큐빙 - 5373

  • [백준] 큐빙 - 5373
  • Platinum V
  • 풀이시간: 240m
  • C++ 풀이
  • 유사 기출 문제(3차원 좌표풀이): 삼성 SW 역량테스트 2024 하반기 오전 1번 문제 /
    미지의 공간 탈출

문제해설

(미작성)

접근법

3차원 큐브에서 각 면의 좌표값을 주어진 이동 규칙에 따라 좌표를 변환하면 되는 문제다.

좌표 변환은 직접 회전하는 면맞닿은 한 행/열만 계산하면 된다. 로직은 move() 함수에 구현했으며, 직접 큐브를 그려보며 좌표의 규칙을 파악하는 과정이 매우 중요하다.

현재는 삼성 SW 역량테스트 환경에 맞춰 문제를 풀고 있어 freopen()을 사용해 입출력을 처리하고, 디버깅을 위한 display() 함수도 구현했다. 다만, 이러한 부분은 문제 해결과는 직접적인 연관이 없다.

#define _CRT_SECURE_NO_WARNINGS

#include<iostream>
#include <string>
#include <unordered_map>
#include<cstring>
using namespace std;

const int MAX = 3;

int N;

string color = "wyrogb"; // 개선: int color[6] = { 'w', 'y', 'r', 'o', 'g', 'b' };
unordered_map<char, int> dmap = { {'U', 0}, {'D', 1}, {'F', 2}, {'B', 3}, {'L', 4}, {'R', 5} };
char board[6][MAX][MAX]; // 윗, 아래, 앞, 뒤, 왼, 오

void move(string cmd);
void display_up(int k);
void display();

int main(int argc, char** argv)
{
	ios::sync_with_stdio(0);
	cin.tie(0);

	int test_case;
	int T;
	
	freopen("input.txt", "r", stdin);
	//cin >> T;
	T = 1;

	//display();

	for (test_case = 1; test_case <= T; ++test_case)
	{
		cin >> N;
		while (N--) {
			for (int k = 0; k < 6; k++) {
				fill(&board[k][0][0], &board[k][0][0] + 9, color[k]); // 배열이 주소값을 가지는 것을 이용하는 방법: fill(board[k][0], board[k][3], color[k]);
			}
			int t;
			cin >> t;
			//cin.ignore(0); // cin.getline() 이랑 같이 쓸 때만 필요
			while (t--) {
				string cmd;
				cin >> cmd;
				move(cmd);
				//cout << s << "\n";
				//display();
			}
			display_up(0);
		}
	}
	return 0;//정상종료시 반드시 0을 리턴해야합니다.
}

char backup[6][MAX][MAX];

void rotate_self(const int d, const bool c) {
	for (int i = 0; i < 3; i++) {
		for (int j = 0; j < 3; j++) {
			if (!c) board[d][i][j] = backup[d][j][2 - i];
			else board[d][i][j] = backup[d][2 - j][i];
		}
	}

}
void move(string cmd)
{
	memcpy(backup, board, sizeof(backup));
	//cout << i << "," << j << "->" << 2 - j << "," << i << "\n";
	//board[][][] = backup[][][];
	bool cw = cmd[1] == '+';
	rotate_self(dmap[cmd[0]], cw);
	for (int i = 0; i < 3; i++) {
		for (int j = 0; j < 3; j++) {
			if (cmd == "U-") {
				board[4][i][2] = backup[3][2][2 - i];
				board[2][0][j] = backup[4][j][2];
				board[5][i][0] = backup[2][0][2 - i];
				board[3][2][i] = backup[5][i][0];
			}
			else if (cmd == "U+") {
				board[5][i][0] = backup[3][2][i];
				board[2][0][j] = backup[5][2 - j][0];
				board[4][i][2] = backup[2][0][i];
				board[3][2][j] = backup[4][2 - j][2];
			}
			else if (cmd == "D-") {
				board[5][i][2] = backup[3][0][i];
				board[2][2][j] = backup[5][2 - j][2];
				board[4][i][0] = backup[2][2][i];
				board[3][0][j] = backup[4][2 - j][0];
			}
			else if (cmd == "D+") {
				board[4][i][0] = backup[3][0][2 - i];
				board[2][2][j] = backup[4][j][0];
				board[5][i][2] = backup[2][2][2 - i];
				board[3][0][j] = backup[5][j][2];
			}
			else if (cmd == "F-") {
				board[4][2][j] = backup[0][2][j];
				board[1][2][j] = backup[4][2][j];
				board[5][2][j] = backup[1][2][j];
				board[0][2][j] = backup[5][2][j];
			}
			else if (cmd == "F+") {
				board[5][2][j] = backup[0][2][j];
				board[1][2][j] = backup[5][2][j];
				board[4][2][j] = backup[1][2][j];
				board[0][2][j] = backup[4][2][j];
			}
			else if (cmd == "B-") {
				board[4][0][j] = backup[1][0][j];
				board[0][0][j] = backup[4][0][j];
				board[5][0][j] = backup[0][0][j];
				board[1][0][j] = backup[5][0][j];
			}
			else if (cmd == "B+") {
				board[5][0][j] = backup[1][0][j];
				board[0][0][j] = backup[5][0][j];
				board[4][0][j] = backup[0][0][j];
				board[1][0][j] = backup[4][0][j];
			}
			else if (cmd == "L-") {
				board[1][i][2] = backup[3][2 - i][0];
				board[2][i][0] = backup[1][2 - i][2];
				board[0][i][0] = backup[2][i][0];
				board[3][i][0] = backup[0][i][0];
			}
			else if (cmd == "L+") {
				board[0][i][0] = backup[3][i][0];
				board[2][i][0] = backup[0][i][0];
				board[1][i][2] = backup[2][2 - i][0];
				board[3][i][0] = backup[1][2 - i][2];
			}
			else if (cmd == "R-") {
				board[0][i][2] = backup[3][i][2];
				board[2][i][2] = backup[0][i][2];
				board[1][i][0] = backup[2][2 - i][2];
				board[3][i][2] = backup[1][2 - i][0];
			}
			else if (cmd == "R+") {
				board[1][i][0] = backup[3][2 - i][2];
				board[2][i][2] = backup[1][2 - i][0];
				board[0][i][2] = backup[2][i][2];
				board[3][i][2] = backup[0][i][2];
			}
		}
	}
}

void display_up(int k) {
	for (int i = 0; i < 3; i++) {
		for (int j = 0; j < 3; j++) {
			cout << board[k][i][j];
		}
		cout << "\n";
	}
}

void display() {
	for (int x = 0; x < 9; x++) {
		for (int y = 0; y < 12; y++) {
			if (x >= 0 && x < 3 && y >= 3 && y < 6) {
				cout << board[3][x % 3][y % 3];
			}
			else if (x >= 3 && x < 6 && y >= 0 && y < 3) {
				cout << board[4][x % 3][y % 3];
			}
			else if (x >= 3 && x < 6 && y >= 3 && y < 6) {
				cout << board[0][x % 3][y % 3];
			}
			else if (x >= 3 && x < 6 && y >= 6 && y < 9) {
				cout << board[5][x % 3][y % 3];
			}
			else if (x >= 3 && x < 6 && y >= 9 && y < 12) {
				cout << board[1][x % 3][y % 3];
			}
			else if (x >= 6 && x < 9 && y >= 3 && y < 6) {
				cout << board[2][x % 3][y % 3];
			}
			else {
				cout << " ";
			}
		}
		cout << "\n";
	}
}

오늘의 회고

삼성의 최근 기출 문제인 미지의 공간 탈출 (2024 하반기 오전 1번)을 시도했다. 예시 입력은 통과했지만 실제 테스트 케이스에서는 실패하여, 구조가 유사한 3차원 좌표 문제를 먼저 풀어보기로 했다.

문제를 해결하는 동안 규칙을 찾기 위해 여러 방법을 고민했지만, 결국 직접 좌표를 변환하는 방식으로 접근했다. 노가다성 풀이였지만, 4시간 만에 해결할 수 있었다.

     ┌B──┐
     │ 3 │
  ┌L─┼U───┼R──┼D──┐ 
  │ 4│ 0 │ 5 │ 1 │
  └──┼────┼───┼───┘ 
     │ 2 │ 
     └F──┘

가장 고민한 부분은 좌표계 기준이었다.
모든 면의 좌상단을 (0, 0)으로 둘 것인지, 아니면 윗면(U)을 기준으로 해당 면의 위쪽이 (0, 0)이 되도록 맞출 것인지 결정이 필요했다. 하지만 아랫면(D)에서 기준이 모호해지는 문제가 있어, 모든 평면의 좌상단을 (0, 0)으로 통일하여 좌표를 계산하기로 했다.

또한, 직접 좌표를 변환하는 방식은 휴먼 에러가 발생하기 쉬워, 실제 시험 환경에서 제대로 적용할 수 있을지에 대한 우려가 있다.
향후에는 3차원 좌표 문제에 대한 보편적인 풀이 방법에 대해 알아보고, 효율적으로 처리할 수 있는 방식에 대해 고민해야겠다.

0개의 댓글