알고리즘/BaekJoon

백준 14499 : 주사위 굴리기

꾸준하게 :) 2020. 3. 22. 18:21

문제 링크입니다 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개의 줄에 지도에 쓰여 있는 수가 북쪽부터 남쪽으로, 각 줄은 서쪽부터 동쪽 순서대로 주어진다. 주사위를 놓은 칸에 쓰여 있는 수는 항상 0이다. 지도의 각 칸에 쓰여 있는 수는 10을 넘지 않는 자연수 또는 0이다. 마

www.acmicpc.net

N x M 지도에서 주사위를 굴릴 때마다 주사위의 맨 위에 있는 숫자를 출력해야 하는 문제였습니다. 문제에서 주어진 내용과 해결 절차는 다음과 같습니다.

 

- 가장 처음에는 주사위의 모든 면에 0이 적혀져 있고, 각 칸에는 정수가 하나씩 쓰여져 있습니다.

 

- 주사위를 굴렸을 때, 이동한 칸에 쓰여 있는 수가 0이면, 주사위의 바닥면에 있는 수가 칸에 복사되고, 0이 아닌 경우에는 칸에 쓰여 있는 수가 주사위의 바닥면으로 복사되면서 칸에 쓰여 있는 수는 0이 됩니다.

 

- 이동 명령은 동쪽은 1, 서쪽은 2, 북쪽은 3, 남쪽은 4로 주어지고, 주사위는 지도의 바깥으로 이동시킬 수 없습니다.

 

[1] 문제에서 주어지는 입력을 받기 위한 변수들과 주사위의 맨 위(up), 맨 밑(down), 오른쪽(right), 왼쪽(left), 앞 쪽(front), 뒤 쪽(back)을 나타내는 변수를 각각 선언합니다.( u, d, r, l, f, b ) 또한, 명령에 맞게 동서남북을 나타내는 방향 배열을 각각 dy, dx로 선언합니다.

 

[2] 명령의 횟수 k번만큼 반복하며 이동 명령에 해당하는 주사위의 다음 좌표를 결정합니다. 단, 해당 좌표가 지도의 범위를 벗어나면 무시해야합니다.

 

[3] 주사위의 맨 밑을 나타내는 변수(d)를 미리 저장해놓고 이동 명령에 따라 u, d, r, l, f, b를 결정합니다.

- 예를 들어, 동쪽으로 굴리는 명령에서는 맨 밑의 값은 오른쪽 값으로 바뀌므로 'd = r' 이런식으로 결정합니다.

 

[4] 다음 좌표와 주사위를 굴렸을 때의 모든 면에 대한 값을 결정한 후, 지도의 다음 칸에 적힌 값이 0이면 결정된 주사위의 바닥면의 값(d)을 칸으로 복사해주고, 0이 아니라면 칸에 적힌 값을 d에 넣어주고 칸을 0으로 만듭니다.

 

[5] 다음 좌표의 값을 각각 현재 좌표를 나타내는 변수에 넣어주고 맨 위(u) 값을 출력합니다.

 

 

[소스코드]

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include<iostream>
using namespace std;
 
// [1] 입력을 받기 위한 변수들, 지도 : map, 명령 : move_
int n, m, y, x, k, map[20][20], move_[1000];
 
// [1] 주사위의 6개 면에 적힌 값을 나타내는 변수 선언
//     up, down, right, left, front, back
int u, d, r, l, f, b;
 
// [1] 동쪽 1, 서쪽 2, 북쪽 3, 남쪽 4 이므로 각각 0번째에는 0을 넣어줍니다
const int dy[] = { 0,0,0,-1,1 };
const int dx[] = { 0,1,-1,0,0 };
 
void solve(void) {
 
    // [2] k번 명령을 수행하기 위해 반복합니다
    for (int i = 0; i < k; i++) {
 
        // [2] 다음칸의 좌표를 입력받은 명령을 통해 결정합니다
        int yy = y + dy[move_[i]];
        int xx = x + dx[move_[i]];
 
        // [2] 배열의 범위를 벗어났다면 무시합니다
        if (yy < 0 || yy >= n || xx < 0 || xx >= m)
            continue;
 
        // [3] 주사위 맨 밑의 값을 미리 저장하고
        int temp = d;
 
        // [3] 각 명령에 따른 주사위의 각 면에 해당하는 값을 결정합니다
        if (move_[i] == 1)
            d = r, r = u, u = l, l = temp;
        else if (move_[i] == 2
            d = l, l = u, u = r, r = temp;
        else if (move_[i] == 3)
            d = b, b = u, u = f, f = temp;
        else
            d = f, f = u, u = b, b = temp;
 
        // [4] 이동한 다음 칸의 값이 0이라면, 주사위 맨 밑 값을 넣어주고
        if (!map[yy][xx]) map[yy][xx] = d;
        else {
 
            // [4] 0이 아니라면 주사위 맨 밑 값에 칸의 값을 넣어주고
            //     해당 칸을 0으로 만들어줍니다
            d = map[yy][xx];
            map[yy][xx] = 0;
        }
 
        // [5] 주사위가 이동했으므로 현재 좌표를 나타내는 변수에
        //     이동한 좌표를 넣어주고
        y = yy, x = xx;
 
        // [5] 이동할때마다 맨 위의 값(u)을 출력합니다
        cout << u << '\n';
    }
}
 
int main(void) {
    cin >> n >> m >> y >> x >> k;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            cin >> map[i][j];
    for (int i = 0; i < k; i++)
        cin >> move_[i];
    solve();
    return 0;
}
cs

 

'알고리즘 > BaekJoon' 카테고리의 다른 글

백준 1012 : 유기농 배추  (0) 2020.04.21
백준 14891 : 톱니바퀴  (0) 2020.03.24
백준 1181 : 단어 정렬  (0) 2020.03.15
백준 15666 : N과 M(12)  (0) 2020.03.14
백준 15665 : N과 M(11)  (0) 2020.03.11