큐빙
링크: https://www.acmicpc.net/problem/5373
문제
문제 접근
- 문제 자체의 이해가 그다지 어렵지는 않았다.
- 큐브의 각 면이 w(white), y(yellow), r(red), o(orange), g(green), b(blue)로 주어져있다.
- 각 테스트 케이스 별로 면을 돌린 뒤에 top의 큐브가 어떤 패턴인지 출력하는 문제이다.
- 큐브의 각 면을 저장할 배열과 적절하게 시계방향 또는 반시계 방향으로 돌리는 함수만 만들면 된다. 너무 간단하다!라고 생각했다.
풀이 힌트
큐브의 각 면 저장
각 면은 2차원 배열 char side[3][4]로 표현할 수 있다. 문자열(char 배열)이기 때문에 null 자리 포함
각 면을 회전시키는 함수
- 각 면의 돌리는 방향은 + 또는 -으로 주어진다.
시계방향의 경우 기존 i는 j로, j는 N - 1 - i와 대응된다.
반시계방향의 경우 기존 i는 N - 1 - j로, j는 i와 대응된다.
여기서 N - 1은 마지막 요소를 가리킨다.
- 하나의 면은 인접한 4개의 면과 상호작용해야 하기 때문에 어떤 면과 연결할지를 결정해야 한다.
자신이 이해하기 편한 방식으로 잘 결정하는 것이 좋을 것 같다. 가장 끔찍한 노가다를 경험했다.
구현에서 가장 실수가 잦을 것이라 생각하는 부분이다.
- 어느 부분과 상호작용할지 결정했다면, 회전 함수를 구현하자.
UP을 예시로 보자.
각 면의 인접한 면을 보면 해당 면이 회전하는 방향대로 회전할 수 있음을 발견할 수 있다.
회전하는 함수를 하나만 구현하면 5 * 5 배열을 회전시키면 되기 때문에 문제가 더 간단해진다!
한 면과 상하좌우로 인접한 가리킬 char 포인터 배열을 다음과 같이 초기화한다. (UP을 예시로 본다.)
인덱스가 우하향으로 진행하기 때문에 BACK과 RIGHT는 반대로 진행한다는 점에 주의하자.
for (int i = 0; i < 3; ++i) {
// adj up
cube_side[UP][0][i + 1] = &(cube[BACK][0][2 - i]);
// adj down
cube_side[UP][4][i + 1] = &(cube[FRONT][0][i]);
// adj left
cube_side[UP][i + 1][0] = &(cube[LEFT][0][i]);
// adj right
cube_side[UP][i + 1][4] = &(cube[RIGHT][0][2 - i]);
}
초기화를 이 악물고 눈 부릅뜨고 꼼꼼히 해준다면, 문제 해결은 어렵지 않다.
초기화가 가장 어려운 문제였다.
코드
주의점
- 각 테스트 케이스는 모든 면이 처음 상태로 돌아간 뒤 다시 계산해야 한다.
#include <iostream>
using namespace std;
enum e_cube {
UP,
DOWN,
FRONT,
BACK,
LEFT,
RIGHT
};
int N, C;
char input[3];
char cube[7][4][4];
char *cube_side[6][6][6];
void rotate(int side, bool is_plus) {
char temp[6][6];
for (int i = 0; i < 6; ++i) {
for (int j = 0; j < 6; ++j) {
if (cube_side[side][i][j] != 0)
temp[i][j] = *(cube_side[side][i][j]);
}
}
if (!is_plus) {
for (int i = 0; i < 6; ++i) {
for (int j = 0; j < 6; ++j) {
if (cube_side[side][i][j] != 0)
*(cube_side[side][i][j]) = temp[j][4- i];
}
}
} else {
for (int i = 0; i < 6; ++i) {
for (int j = 0; j < 6; ++j) {
if (cube_side[side][i][j] != 0)
*(cube_side[side][i][j]) = temp[4- j][i];
}
}
}
}
void spin_cube(char side, bool is_plus) {
// dir에 따라 90도 혹은 -90도 회전
// 영향을 받는 인접한 4면 변경
if (side == 'U') {
rotate(UP, is_plus);
} else if (side == 'D') {
rotate(DOWN, is_plus);
} else if (side == 'F') {
rotate(FRONT, is_plus);
} else if (side == 'B') {
rotate(BACK,is_plus);
} else if (side == 'L') {
rotate(LEFT, is_plus);
} else {
rotate(RIGHT, is_plus);
}
}
void init_pointer() {
// up
for (int i = 0; i < 3; ++i) {
// adj up
cube_side[UP][0][i + 1] = &(cube[BACK][0][2 - i]);
// adj down
cube_side[UP][4][i + 1] = &(cube[FRONT][0][i]);
// adj left
cube_side[UP][i + 1][0] = &(cube[LEFT][0][i]);
// adj right
cube_side[UP][i + 1][4] = &(cube[RIGHT][0][2 - i]);
}
// down
for (int i = 0; i < 3; ++i) {
cube_side[DOWN][0][i + 1] = &(cube[FRONT][2][i]);
cube_side[DOWN][4][i + 1] = &(cube[BACK][2][2 - i]);
cube_side[DOWN][i + 1][0] = &(cube[LEFT][2][2 - i]);
cube_side[DOWN][i + 1][4] = &(cube[RIGHT][2][i]);
}
// front
for (int i = 0; i < 3; ++i) {
cube_side[FRONT][0][i + 1] = &(cube[UP][2][i]);
cube_side[FRONT][4][i + 1] = &(cube[DOWN][0][i]);
cube_side[FRONT][i + 1][0] = &(cube[LEFT][i][2]);
cube_side[FRONT][i + 1][4] = &(cube[RIGHT][i][0]);
}
// back
for (int i = 0; i < 3; ++i) {
cube_side[BACK][0][i + 1] = &(cube[UP][0][2 - i]);
cube_side[BACK][4][i + 1] = &(cube[DOWN][2][2 - i]);
cube_side[BACK][i + 1][0] = &(cube[RIGHT][i][2]);
cube_side[BACK][i + 1][4] = &(cube[LEFT][i][0]);
}
// left
for (int i = 0; i < 3; ++i) {
cube_side[LEFT][0][i + 1] = &(cube[UP][i][0]);
cube_side[LEFT][4][i + 1] = &(cube[DOWN][2 - i][0]);
cube_side[LEFT][i + 1][0] = &(cube[BACK][i][2]);
cube_side[LEFT][i + 1][4] = &(cube[FRONT][i][0]);
}
// right
for (int i = 0; i < 3; ++i) {
cube_side[RIGHT][0][i + 1] = &(cube[UP][2 - i][2]);
cube_side[RIGHT][4][i + 1] = &(cube[DOWN][i][2]);
cube_side[RIGHT][i + 1][0] = &(cube[FRONT][i][2]);
cube_side[RIGHT][i + 1][4] = &(cube[BACK][i][0]);
}
}
void init() {
string side_color = "wyrogb";
for (int i = 0; i < 6; ++i) {
for (int j = 0; j < 3; ++j) {
for (int k = 0; k < 3; ++k) {
cube[i][j][k] = side_color[i];
cube_side[i][j + 1][k + 1] = &(cube[i][j][k]);
}
}
}
}
void print_top() {
for (int j = 0; j < 3; ++j) {
cout << cube[UP][j] << '\n';
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> N;
init_pointer();
for (int i = 0; i < N; ++i) {
cin >> C;
init();
for (int j = 0; j < C; ++j) {
cin >> input;
spin_cube(input[0], input[1] == '+');
}
print_top();
}
}
※ 오류나 개선점이 있다면 알려주세요 :) 신속히 수정하겠습니다.
'Algorithms > 백준(BOJ)' 카테고리의 다른 글
[백준 8980] 택배(C++) (3) | 2024.10.13 |
---|---|
[백준 11003] 최솟값 찾기(C++) (0) | 2024.10.06 |
[백준 6549] 히스토그램에서 가장 큰 직사각형(C++) (2) | 2024.09.29 |
[백준 2240] 자두나무(C++) (2) | 2024.09.29 |
[백준 15486] 퇴사 2(C++) (0) | 2024.09.25 |