[java,백준5373]큐빙 - 3D 큐브의 2D 시뮬레이션 구현
3차원 루빅스 큐브를 2차원 배열로 변환하여 각 면의 회전을 시뮬레이션하는 구현 문제입니다.
예시 시각화:
아래 큐브 전개도가 변하는 모습을 이해한다면 충분히 풀 수 있을 것이다!
[w][w][w]
[w][w][w]
[w][w][w]
[g][g][g][r][r][r][b][b][b][o][o][o]
[g][g][g][r][r][r][b][b][b][o][o][o]
[g][g][g][r][r][r][b][b][b][o][o][o]
[y][y][y]
[y][y][y]
[y][y][y]
R+ 를 한다면?
[w, w, r]
[w, w, r]
[w, w, r]
[g, g, g][r, r, y][b, b, b][w, o, o]
[g, g, g][r, r, y][b, b, b][w, o, o]
[g, g, g][r, r, y][b, b, b][w, o, o]
[y, y, o]
[y, y, o]
[y, y, o]
U+ 를 한다면?
[w, w, w]
[w, w, w]
[r, r, r]
[r, r, y][b, b, b][w, o, o][g, g, g]
[g, g, g][r, r, y][b, b, b][w, o, o]
[g, g, g][r, r, y][b, b, b][w, o, o]
[y, y, o]
[y, y, o]
[y, y, o]
풀이
구현 시 주의사항
💡 3차원 큐브를 2차원으로 표현하는 과정에서 방향 설정이 매우 중요함. 회전 시 면과 인접한 면들의 변화를 정확히 파악하자!
디버깅 꼭꼭 하자!!!! => 추천 링크: 루빅큐브 회전모습 확인
💡 -방향은 +를 3번한 것과 동일하다. (시계 방향 3번 = 반시계 방향 1번)
핵심 구현 사항
- 각 면을 3x3 2차원 배열로 표현 (총 6개)
- 시계 방향 회전만 구현하자 (총 6개 = R+ L+ U+ D+ F+ B+)
- 반시계는 해당 함수를 3번 사용하면 되기 때문!
- 회전 시 인접면들의 변화 처리 꼭! 꼭! 다시 체크!!
- 디버깅 코드도 있으니까 디버깅으로 더블체크 하길 강조한다.
면 회전 구현
//회전로직은 시계방향: B[x][y]=A[N-1-y][x] 를 이용하면 된다.
private static void rotate(char[][] value) {
char[][] temp = new char[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
temp[i][j] = value[i][j]; //copy
}
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
value[i][j] = temp[3-1-j][i];
}
}
}
반시계 방향 처리
if (roll.charAt(0) == 'U') {
UPlus();
//반시계 방향의 경우 "시계방향x3" 이므로 2번 더 돌려야 함
if (roll.charAt(1) == '-') {
UPlus();
UPlus();
}
}
전체 코드
U+ L+ R+ L+ F+ B+ 함수를 구현하는게 가장 중요하다.
해당 함수 코드는 참고로만 확인하고, 직접 전개도의 움직임을 보고 짜는게 구현하기 더 수월할 것이다.
public class 큐빙_5373 {
static int N;
static String[] rolling; //input
static char[][] front = new char[3][3];
static char[][] up = new char[3][3];
static char[][] left = new char[3][3];
static char[][] right = new char[3][3];
static char[][] down = new char[3][3];
static char[][] back = new char[3][3];
private static void solve() {
for (int i = 0; i < N; i++) {
String roll=rolling[i];
if (roll.charAt(0) == 'U') {
UPlus();
//반시계 방향의 경우 "시계방향x3" 이므로 2번 더 돌려야 함
if (roll.charAt(1) == '-') {
UPlus();
UPlus();
}
}else if (roll.charAt(0) == 'D') {
DPlus();
//반시계 방향의 경우 "시계방향x3" 이므로 2번 더 돌려야 함
if (roll.charAt(1) == '-') {
DPlus();
DPlus();
}
}else if (roll.charAt(0) == 'F') {
FPlus();
//반시계 방향의 경우 "시계방향x3" 이므로 2번 더 돌려야 함
if (roll.charAt(1) == '-') {
FPlus();
FPlus();
}
}else if (roll.charAt(0) == 'B') {
BPlus();
//반시계 방향의 경우 "시계방향x3" 이므로 2번 더 돌려야 함
if (roll.charAt(1) == '-') {
BPlus();
BPlus();
}
}else if (roll.charAt(0) == 'L') {
LPlus();
//반시계 방향의 경우 "시계방향x3" 이므로 2번 더 돌려야 함
if (roll.charAt(1) == '-') {
LPlus();
LPlus();
}
}else if (roll.charAt(0) == 'R') {
RPlus();
//반시계 방향의 경우 "시계방향x3" 이므로 2번 더 돌려야 함
if (roll.charAt(1) == '-') {
RPlus();
RPlus();
}
}
//debug 모든 면 출력
// System.out.println(rolling[i]);
// allPrint();
}
}
public static void main(String[] args) throws IOException {
//input
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
for (int t = 0; t < T; t++) {
init(); //매번 큐브배열 초기화
//input
N = Integer.parseInt(br.readLine());
StringTokenizer stk = new StringTokenizer(br.readLine(), " ");
rolling = new String[N + 1];
for (int i = 0; i < N; i++) {
rolling[i] = stk.nextToken();
}
//run
solve();
//output
for (int i = 0; i < 3; i++) {
System.out.print(up[i]);
System.out.println();
}
}
}
private static void BPlus() {
rotate(back);
//up->right->down->left
char[] temp = new char[3];
for (int i = 0; i < 3; i++) {
temp[i]=up[0][i]; //copy
}
for (int i = 0; i < 3; i++) {
up[0][i]=right[i][2];
}
for (int i = 0; i < 3; i++) {
right[i][2]=down[2][2-i];
}
for (int i = 0; i < 3; i++) {
down[2][i]=left[i][0];
}
for (int i = 0; i < 3; i++) {
left[i][0]=temp[2-i];
}
}
private static void LPlus() {
rotate(left);
//front->up->back->down
char[] temp = new char[3];
for (int i = 0; i < 3; i++) {
temp[i] = front[i][0]; //copy
}
for (int i = 0; i < 3; i++) {
front[i][0]=up[i][0];
}
for (int i = 0; i < 3; i++) {
up[i][0]=back[2-i][2];
}
for (int i = 0; i < 3; i++) {
back[2-i][2]=down[i][0];
}
for (int i = 0; i < 3; i++) {
down[i][0]=temp[i];
}
}
private static void DPlus() {
rotate(down);
//front->left->back->right
char[] temp = Arrays.copyOfRange(front[2],0,3); //copy
for (int i = 0; i < 3; i++) {
front[2][i]=left[2][i];
}
for (int i = 0; i < 3; i++) {
left[2][i]=back[2][i];
}
for (int i = 0; i < 3; i++) {
back[2][i]=right[2][i];
}
for (int i = 0; i < 3; i++) {
right[2][i]=temp[i];
}
}
private static void FPlus() {
rotate(front);
//up->left->down->right
char[] temp = new char[3];
for (int i = 0; i < 3; i++) {
temp[i]=up[2][i]; //copy
}
for (int i = 0; i < 3; i++) {
up[2][i]=left[2-i][2];
}
for (int i = 0; i < 3; i++) {
left[i][2]=down[0][i];
}
for (int i = 0; i < 3; i++) {
down[0][i]=right[2-i][0];
}
for (int i = 0; i < 3; i++) {
right[i][0]=temp[i]; //방향 주의
}
}
private static void RPlus() {
rotate(right);
//front->down->back->up
char[] temp = new char[3];
for (int i = 0; i < 3; i++) {
temp[i] = front[i][2]; //copy
}
for (int i = 0; i < 3; i++) {
front[i][2]=down[i][2];
}
for (int i = 0; i < 3; i++) {
down[i][2]=back[2-i][0];
}
for (int i = 0; i < 3; i++) {
back[2-i][0]=up[i][2];
}
for (int i = 0; i < 3; i++) {
up[i][2]=temp[i];
}
}
private static void UPlus() {
rotate(up);
//front->right->back->left
char[] temp = Arrays.copyOfRange(front[0],0,3); //copy
for (int i = 0; i < 3; i++) {
front[0][i]=right[0][i];
}
for (int i = 0; i < 3; i++) {
right[0][i]=back[0][i];
}
for (int i = 0; i < 3; i++) {
back[0][i]=left[0][i];
}
for (int i = 0; i < 3; i++) {
left[0][i]=temp[i];
}
}
//회전로직은 시계방향: B[x][y]=A[N-1-y][x] 를 이용하면 된다.
private static void rotate(char[][] value) {
char[][] temp = new char[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
temp[i][j] = value[i][j]; //copy
}
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
value[i][j] = temp[3-1-j][i];
}
}
}
private static void init() {
int cnt=0; //debug
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
// front[i][j]=(char)(++cnt+'0'); //rotate debug 용도
// up[i][j]=(char)(cnt+'0'); //rotate debug 용도
// down[i][j]=(char)(cnt+'0'); //rotate debug 용도
// back[i][j]=(char)(cnt+'0'); //rotate debug 용도
// left[i][j]=(char)(cnt+'0'); //rotate debug 용도
// right[i][j]=(char)(cnt+'0'); //rotate debug 용도
// up[i][j]='w'; //전개도 링크 debug 용도(그림 순서 달라서)
// down[i][j]='y'; //전개도 링크 debug 용도
// front[i][j]='g'; //전개도 링크 debug 용도
// back[i][j]='b'; //전개도 링크 debug 용도
// left[i][j]='o'; //전개도 링크 debug 용도
// right[i][j]='r'; //전개도 링크 debug 용도
up[i][j]='w';
down[i][j]='y';
front[i][j]='r';
back[i][j]='o';
left[i][j]='g';
right[i][j]='b';
}
}
}
private static void allPrint() {
//전개도로 출력
for(int i=0; i<3; i++) {
System.out.print(" ");
System.out.println(Arrays.toString(up[i]));
}
for(int i=0; i<3; i++) {
System.out.print(Arrays.toString(left[i]));
System.out.print(Arrays.toString(front[i]));
System.out.print(Arrays.toString(right[i]));
System.out.println(Arrays.toString(back[i]));
}
for (int i = 0; i < 3; i++) {
System.out.print(" ");
System.out.println(Arrays.toString(down[i]));
}
}
}
/*
아래 링크 전개도 보고 디버깅 하기.
https://rubiks-cube-solver.com/fr/#
1
3
U+ R+ R+
1
3
R+ U+ U+
1
3
U+ F+ F+
1
3
R+ D+ D+
1
3
D+ L+ L+
1
3
D+ B+ B+
*/
주관적인 생각의 풀이이므로 틀린 부분 지적은 언제나 환영합니다⚡
댓글남기기