[BOJ 5373] 큐빙

1 minute read

풀이

단순한 구현 문제이나 생각이 꼬이지 않으면서 구현을 잘 해주어야하는 문제이다.

총 6 면(위 아래 앞 뒤 좌 우)의 큐브가 각각 회전하면서 어떻게 되는지를 생각해야하는데, 큐브의 상태를 어떻게 정의하느냐에 따라 구현 난이도가 높아질 수 있다.

아래의 코드는 큐브의 면을 0,1,2,3,4,5 로 번호를 지정하고, 각 면에서 한 타일 당 좌상단부터 0~8 까지의 숫자를 부여한 상태이다.
이 상태에서 각각의 회전하는 경우에 따른 함수를 구현한 것이다.

코드

#include <iostream>

using namespace std;

void init(int cube[6][3][3]){
    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]=i;
            }
        }
    }
}

char face[7]="UDFBLR";
char color[7]="wyrogb";
int matrix[6][4]={ {2,5,3,4},{2,4,3,5},{0,4,1,5},{0,5,1,4},{0,3,1,2},{0,2,1,3} };//ccw - represent reference side and next side w/ ccw
int refer[6][4]={ {0,0,0,0},{2,2,2,2},{2,1,0,3},{0,1,2,3},{3,1,3,3},{1,1,1,3} };//ccw - represent turn part
int turn[4][3]={ {0,1,2},{2,5,8},{8,7,6},{6,3,0} };

void makeSide(int cube[6][3][3], int side[3], int f){
    int r=matrix[f][0];
    for(int i=0; i<3; i++){
        int y=turn[refer[f][0]][i]/3, x=turn[refer[f][0]][i]%3;
        side[i]=cube[r][y][x];
    }
}

void printCube(int cube[6][3][3]){
    for(int i=0; i<3; i++){
        for(int j=0; j<3; j++){
            cout << color[cube[0][i][j]];
        }
        cout << "\n";
    }
}

void turnSide(int cube[6][3][3], int side[3], int f, bool ccw){
        for(int i=3; i; i--){
            int tar, r;
            int t = (ccw?i:(4-i));
            int tt=(ccw?((i+1)%4):3-i);

            r = matrix[f][t];
            tar = matrix[f][tt];

            for(int j=0; j<3; j++){
                int y=turn[refer[f][t]][j]/3, x=turn[refer[f][t]][j]%3;
                int ty=turn[refer[f][tt]][j]/3, tx=turn[refer[f][tt]][j]%3;
                cube[tar][ty][tx]=cube[r][y][x];
            }
        }

        int last = (ccw?1:3);

        for(int i=0; i<3; i++){
            int y=turn[refer[f][last]][i]/3, x=turn[refer[f][last]][i]%3;
            cube[matrix[f][last]][y][x] = side[i];
        }
}

void turnFace(int cube[6][3][3], int next[3][3], int f){
    for(int i=0; i<3; i++){
        for(int j=0; j<3; j++){
            cube[f][i][j]=next[i][j];
        }
    }
}

void rotateCube(int cube[6][3][3], int f, bool ccw){
    int next[3][3];
    if(!ccw){
        for(int i=0; i<3; i++){
            for(int j=0; j<3; j++){
                next[j][2-i]=cube[f][i][j];
            }
        }
    }
    else{
        for(int i=0; i<3; i++){
            for(int j=0; j<3; j++){
                next[2-j][i]=cube[f][i][j];
            }
        }
    }
    turnFace(cube, next, f);
    int side[3];
    makeSide(cube, side, f);
    turnSide(cube, side, f, ccw);
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    int TC;
    cin >> TC;
    while(TC--){
        int N;
        cin >> N;
        int cube[6][3][3];

        init(cube);

        while(N--){
            char f, t;
            cin >> f >> t;
            for(int i=0; i<6; i++){
                if(face[i]==f){
                    if(t=='+') rotateCube(cube,i,0);
                    else rotateCube(cube,i,1);
                    break;
                }
            }
        }
        printCube(cube);
    }
    return 0;
}

개선할 점

  1. 큐브를 펼쳐서 전개도로 생각하게 될 경우 훨씬 쉽다.
  2. 그니까 구현할 때 조금 더 효율적인 방법을 생각해보자.

여담이지만 이 문제를 이렇게 구현하면서 조금 고통받았지만 덕분에 구현력이 조금 올라간 느낌적인 느낌이다.
때로는 힘든 길이 도움이 되기도…

Leave a comment