그냥 블로그

[백준/C++] 14499. 주사위 굴리기 본문

C++/백준

[백준/C++] 14499. 주사위 굴리기

코딩하는 공대생 2023. 12. 8. 21:08
반응형
 

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

 

[문제]

=> 처음에 독해하기 좀 어려웠는데 지도와 주사위, 시작 점이 주워지고 
명령에 주어진 방향으로 주사위를 '굴리는' 거다. 

 

아래 그림 처럼 주사위를 동쪽으로 굴리면 빨간 밑면은 왼쪽으로 윗면은 오른쪽으로 간다. 
그리고 지도에 닿는 면과 마주보는 면을 출력하면 된다 ㅇㅇ.

 

[풀이 과정]

1. 일단 문제를 보고 규칙을 찾아서 구현하는 문제구나 생각했다.

2. 주사위 규칙을 찾아보려고 이래저래 고민 >> 파란색 방향을 가로 / 초록 방향을 세로로 가정한다. 

    1) 주사위를 세로 방향으로 굴리면 가로는 유지된다. 가로 방향으로 굴려도 동일하다.
     - 주사위를 북쪽, 남쪽으로만 굴린다고 생각하면 2번과 3번은 [4,1,5,6] 어떤 숫자가 바닥에 있건 서쪽 2번, 동쪽 3번을 유지한다.

     - 서쪽, 동쪽으로만 굴려도 [2,1,3,6] 어떤 숫자든 동일하게 4번과 5번이 북, 남을 유지한다. 

    2) 동쪽으로 한번 굴렸을 때, 바닥면은 서쪽으로, 윗면은 동쪽으로 간다.  > 서쪽으로 굴렸을 때도 동일. >>> 배열로 표현

      - [서, 바닥, 동, 윗] 면 순으로 배열 표현이 가능하다. 

      - [북, 바닥, 남, 윗] 면 순으로 세로 또한 가능.  

     => 바닥면의 위치는 방향 벡터로 구분지을 수 있다. 

 

3. 규칙에 맞게 로직을 짜면

    1) 명령어를 입력받는다.

    2) 범위를 벗어나는지 확인 > continue;

    3) 주사위의 바닥면과 나머지 위치를 갱신한다. 

         - dice[2][4] // [세로 : 북, 바닥, 남, 위] 순서로 나타낸다.

                              [가로 : 서, 바닥, 동, 위]

        - pivot_col : 세로 배열에서 바닥을 나타내는 정수 > pivot_col + dy[i] %4로 갱신한다.

        - pivot_row : 가로 베열에서 바닥을 나타내는 정수 

        => pivot_col / row 의 갱신 기준과 방향 배열 순서는 동일함.

    4) y와 x의 위치를 갱신

 

명령어 4를 입력한다고 하면

pivot_ row = 1 / pivot_col=1

4 1 5 6
2 1 3 6

 

4입력

pivot_row = 1 / pivot_col = 2 >> 세로 pivot을 갱신하고

#include<iostream>

using namespace std;

// 동, 서, 북, 남
int dy[] = { 0,0,0,-1,1 };
int dx[] = { 0,1,-1,0,0 };

int N, M, x, y, K; // 세로크기, 가로크기, 주사위 좌표, 명령 K
int board[20][20];

int dice[2][4]; // 세로(북,남), 가로(동,서) 
//북, 중앙, 남, 반대
//서, 중앙 ,동 ,반대

int pivot_col = 1; (세로 기준)
int pivot_row = 1; (가로 기준)

void check_dice(int comm) {
	pivot_col = (pivot_col + dy[comm] + 4) % 4;
	pivot_row = (pivot_row + dx[comm] + 4) % 4;
	
	//주사위랑 board에 숫자 표기
	//반대편 숫자 출력
	if (comm < 3) { // 가로
		dice[0][pivot_col] = dice[1][pivot_row];
		dice[0][(pivot_col + 2) % 4] = dice[1][(pivot_row + 2) % 4];
	}
	else { //세로
		dice[1][pivot_row] = dice[0][pivot_col];
		dice[1][(pivot_row + 2) % 4] = dice[0][(pivot_col + 2) % 4];
	}

	cout << dice[1][(pivot_row + 2) % 4]<<'\n';
	
}

int main() {
	cin >> N >> M >> y >> x >> K;
	fill(&dice[0][0], &dice[0][0] + 2 * 4, 0);
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			cin >> board[i][j];
		}
	}
	int comm;

	for (int i = 0; i < K;i++) {
		cin >> comm;
		int ny = y + dy[comm];
		int nx = x + dx[comm];
        // 범위 넘어서면 ㄴㄴ
		if (ny < 0 || nx < 0 || ny >= N || nx >= M) continue;
		
        // 보드와 주사위의 번호 갱신!
        if (board[y][x]) {
			dice[0][pivot_col] = board[y][x];
			dice[1][pivot_row] = board[y][x];
			board[y][x] = 0;
		}
		else {
			board[y][x] = dice[1][pivot_row];
		}
        
		check_dice(comm);
		y = ny;
		x = nx;
	}

}

 

 

[추가]

1. 문제 풀 때 주사위 숫자를 바꾸면 지도를 0으로 바꾼다던가 하는 곳을 놓쳐서 계속 틀렸음..

2. 또 또 좌표를 헷갈리게 문제내서 계속 틀림 ㅋㅋㅋ

3. 보드와 주사위 번호를 갱신하는 부분을 continue 앞에 썼다가 오류가 있었음... >> continue를 안하고 계속 번호 바꿔가지고 그런듯...

 

 

다른 사람들은 이런식으로 1차원 배열에서 각 방향으로 굴렸을때 바뀌는 법칙?이 있어서 그거로 많이 푼듯

뭐 비슷 한듯 ㅇㅇ??

 

'C++ > 백준' 카테고리의 다른 글

[C++/백준] 2143 두 배열의 합  (1) 2023.12.29
[백준/C++] 보석 도둑  (0) 2023.12.24
[백준/C++] 1005 ACM Craft  (2) 2023.12.03
[백준/C++] 27172 수 나누기 게임  (0) 2023.11.26
[C++/백준] 14891 톱니바퀴  (0) 2023.11.19