알고리즘/구현 & 그리디 & 브루트포스

[백준]JAVA - 14499번: 주사위 굴리기

K.두부 2023. 3. 30. 14:00
반응형

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

🔶 풀이

모든 면이 0으로 채워진 주사위를 굴렸을 때 발생하는 일은 아래와 같다.

 

1. 이동한 칸에 쓰여 있는 수가 0인 경우, 주사위의 바닥면에 쓰여 있는 수를 복사한다.

2. 이동한 칸에 쓰여 있는 수가 0이 아닌 경우, 칸에 쓰여있는 수가 주사위의 바닥면에 복사되고, 칸은 0이 된다.

 

주사위는 지도의 크기에서 벗어날 수 없고, 벗어갔다면 해당 명령은 무시한다.

또한, 주사위를 한 번 굴릴때마다 주사위의 윗면을 출력한다.

 

 

위 설명에 초기 주사위가 어떤 상태로 놓여있는지에 대해서 적혀있다.

사실상 이 부분은 무시해도 무관하다.

 

우리가 신경써야할 건 주사위를 동서남북으로 굴렸을 때 각 각의 면들이 어디로 이동하는지다.

주사위는 어떠한 방향으로 돌려도 변하지 않는 면 2개가 존재한다. 

 

1. 동쪽으로 굴렸을 경우 (앞, 뒷면 그대로 유지)

2. 서쪽으로 굴렸을 경우 (앞, 뒷면 그대로 유지)

3. 북쪽으로 굴렸을 경우 (좌, 우면 그대로 유지)

4. 남쪽으로 굴렸을 경우 (좌, 우면 그대로 유지)

 

필자는 이 부분을 객체 클래스를 만들어서 해결해줬다.

주사위를 굴려주는 부분만 해결해주면 나머지는 어려운 건 없다고 생각된다.

 

<최종코드>

import java.io.*;
import java.util.*;

public class Main {
    static int[] dx = {0, 0, -1, 1};
    static int[] dy = {1, -1, 0, 0};
	
    public static class DiceRoll {
        int top, bot, right, left, front, back;
		
        public DiceRoll(int top, int bot, int right, int left, int front, int back) { 
            this.top = top;
            this.bot = bot;
            this.right = right;
            this.left = left;
            this.front = front;
            this.back = back;
        }
    }
	
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
		
        int N = Integer.parseInt(st.nextToken());   // 맵 크기 x
        int M = Integer.parseInt(st.nextToken());   // 맵 크기 y
        int x = Integer.parseInt(st.nextToken());   // 주사위 위치 x
        int y = Integer.parseInt(st.nextToken());   // 주사위 위치 y
        int cnt = Integer.parseInt(st.nextToken()); // 명령 개수
		
        int[][] map = new int[N][M];
		
        for (int i=0; i<N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j=0; j<M; j++) {
                map[i][j] = Integer.parseInt(st.nextToken());
            }
        }
	
        DiceRoll dice = new DiceRoll(0, 1, 2, 3, 4, 5); // 초기 주사위 셋팅
        int[] diceValue = new int[6]; 
		
        st = new StringTokenizer(br.readLine());
        for (int i=0; i<cnt; i++) {
            int d = Integer.parseInt(st.nextToken());
			
            int top = dice.top;
            int bot = dice.bot;
            int right = dice.right;
            int left = dice.left;
            int front = dice.front;
            int back = dice.back;
			
            int nx = x + dx[d-1];
            int ny = y + dy[d-1];
			
            // 맵을 벗어난 경우 명령 무시
            if (nx < 0 || ny < 0 || nx > N-1 || ny > M-1) continue;
			
            switch (d) {
            case 1:
                dice = new DiceRoll(right, left, bot, top, front, back);
                break;
				
            case 2:
                dice = new DiceRoll(left, right, top, bot, front, back);
                break;
				
            case 3:
                dice = new DiceRoll(front, back, right, left, bot, top);
                break;
				
            case 4:
                dice = new DiceRoll(back, front, right, left, top, bot);
                break;
            }
			
            // 주사위 위치 변경
            x = nx;
            y = ny;
			
            if (map[nx][ny] == 0) {
                map[nx][ny] = diceValue[dice.bot];
            } else {
                diceValue[dice.bot] = map[nx][ny];
                map[nx][ny] = 0;
            }
			
            System.out.println(diceValue[dice.top]);
        }
    }
}
반응형