14499. 주사위 굴리기

2024. 1. 20. 15:25백준

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

 

14499번: 주사위 굴리기

첫째 줄에 지도의 세로 크기 N, 가로 크기 M (1 ≤ N, M ≤ 20), 주사위를 놓은 곳의 좌표 x, y(0 ≤ x ≤ N-1, 0 ≤ y ≤ M-1), 그리고 명령의 개수 K (1 ≤ K ≤ 1,000)가 주어진다. 둘째 줄부터 N개의 줄에 지

www.acmicpc.net

 

풀이

주사위가 굴러가면서 어느 면이 지도와 맞닿는지를 구현하는 게 쉽지 않을 수 있다. 여러 방법이 있겠지만, 필자는 주사위를 크기 4의 덱(deque)과 두 변수로 구현하였다.

주사위의 전개도의 구현

여기서 deque[0]과 deque[2]는 각각 주사위의 밑면과 윗면으로 정의한다. 이렇게 한 다음 주사위의 움직임을 생각해 보자. 주사위를 남북 방향으로 굴릴 경우에는 side L, R의 값이 변하지 않으며, 덱의 front와 back 원소값의 push, pop만 조정해 주면 된다.

주어진 주사위(좌)를 남쪽으로 한 칸(가운데), 북쪽으로 한 칸(우) 굴린 모습

주사위를 동서 방향으로 굴릴 경우는 조금 복잡하다. 동쪽으로 굴릴 경우는 값이 deque[2] → side R → deque[0] → side L → deque[2]의 방향으로 이동한다. 서쪽으로 굴릴 경우는 deque[2] → side L → deque[0] → side R → deque[2]의 방향으로 값이 이동한다.

주어진 주사위(좌)를 동쪽으로 한 칸(가운데), 서쪽으로 한 칸(우) 굴린 모습

앞의 사실을 바탕으로 주사위의 움직임을 구현한다면 나머지는 어렵지 않게 구현이 가능하다.

 

소스코드

#include <iostream>
#include <deque>
#include <algorithm>
using namespace std;

int n, m, x, y, k;
int board[20][20];
deque<int> dice(4);		// 주사위의 상하전후
int sideL, sideR;		// 주사위의 좌우
int arrow;
int dx[] = {0, 0, 0, -1, 1};
int dy[] = {0, 1, -1, 0, 0};

// 굴린 주사위가 범위를 벗어나는지 확인하는 함수
bool invalidRange(int nx, int ny) {
    return nx < 0 || nx >= n || ny < 0 || ny >= m;
}

// 주사위나 지도에 숫자를 덧씌우는 함수
void paint() {
    if(board[x][y] == 0) {
        board[x][y] = dice[0];
    }
    else {
        dice[0] = board[x][y];
        board[x][y] = 0;
    }
}

// 주사위를 특정한 방향으로 굴리는 함수
void roll() {
    cin >> arrow;
    if(invalidRange(x + dx[arrow], y + dy[arrow])) return;
    x += dx[arrow]; y += dy[arrow];
    switch(arrow) {
        case 1:
            swap(sideL, dice[0]);
            swap(dice[0], sideR);
            swap(sideR, dice[2]);
            break;
        case 2:
            swap(sideR, dice[0]);
            swap(dice[0], sideL);
            swap(sideL, dice[2]);
            break;
        case 3:
            dice.push_front(dice.back());
            dice.pop_back();
            break;
        case 4:
            dice.push_back(dice.front());
            dice.pop_front();
            break;
    }
    
    paint();
    cout << dice[2] << '\n';
}

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    cin >> n >> m >> x >> y >> k;
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < m; j++) cin >> board[i][j];
    }
    
    while(k--) {
        roll();
    }
    
    return 0;
}

 

'백준' 카테고리의 다른 글

18809. Gaaaaaaaaaarden  (0) 2024.02.16
16985. Maaaaaaaaaze  (0) 2024.01.27
14891. 톱니바퀴  (0) 2024.01.19
11559. Puyo Puyo  (1) 2024.01.19
2447. 별 찍기 - 10  (0) 2023.12.30