[BOJ/Java] 14499: 주사위 굴리기

2025. 6. 5. 19:16·Problem Solving/BOJ

문제

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

크기가 `N` x `M`인 지도가 있다.

지도에는 주사위가 놓여져 있으며, 주사위 전개도는 다음과 같다.

  2
4 1 3
  5
  6

지도의 칸에는 정수가 쓰여져 있다. 주사위를 굴렸을 때, 이동한 칸의 숫자가 0이면, 주사위의 바닥면의 숫자가 이동한 칸에 복사된다. 0이 아닌 경우 칸에 있는 숫자가 주사위 바닥면에 복사된다.

주사위의 초기 좌표인 `x`, `y`와 `K`번의 주사위의 이동 방향이 주어지면, 이동했을 때마다 주사위 윗면의 숫자를 출력해야 한다.

  • 1 ≤ `N`, `M` ≤ 20
  • 0 ≤ `x` ≤ N-1, 0 ≤ `y` ≤ M-1
  • 1 ≤ K ≤ 1,000

 

풀이

전에 풀었던 주사위 굴리기 2보다 난이도가 낮은 구현 문제다. 그땐 도움을 받아 풀었지만, 이번에는 혼자 힘으로 풀어보았다. 시간은 1시간 조금 넘게 걸렸지만, 나름대로 문제 조건을 잘 정리해서 디버깅까지 해낸 것 같다.

 

구현 문제는 조건을 빼먹지 않고 최대한으로 쪼갤 수 있는 기능을 함수로 나누어 푸는 것이 중요한 것 같다. 그래야 디버깅할 때 어디서 문제가 생기는지 빨리 파악할 수 있다.

 

항상 dx, dy에서 어느 곳을 증가시키고 감소시켜야 어떻게 이동하는 지 헷갈리는데, x와 y가 수학에서의 좌표계와 혼동하곤 한다. 프로그래밍에서의 원점은 좌상단이며, 좌표계는 좌하단이다. x를 변화시키면 수직 이동, y를 변화시키면 평행 이동이다. dx, dy라는 이름을 쓰는 것보다 행과 열을 움직인다는 것을 명시적으로 표현하기 위해서 dr, dc라는 이름을 쓰는 게 더 직관적인 듯하다.

 

코드

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

public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static int n, m, x, y, k;
    static int[] dx = {0, 0, 0, -1, 1}; // 동, 서, 북, 남
    static int[] dy = {0, 1, -1, 0, 0};
    static int[][] map;
    static int[] dice = {0, 0, 0, 0, 0, 0, 0}; // 1-based, 윗면, 북, 동, 서, 남, 아랫면를 의미

    public static void main(String[] args) throws IOException {
        // 지도 상(n x m)에서 주사위를 움직인다.
        // 주사위의 초기 상태는 윗면이 1, 동쪽이 3을 바라보고 있고, (x, y)에서 시작한다.
        // 주사위의 모든 면에는 0이 적혀있다.
        // 주사위를 굴리면 지도 상의 칸 숫자가 바닥면에 복사되며, 지도 숫자는 0이 된다.
        // 이동 명령이 k번 주어지면, 이동할 때의 주사위 상단에 적힌 숫자를 출력한다.
        // 명령은 방향으로 주어진다. 동서남북 -> 1243
        st = new StringTokenizer(br.readLine());
        n = Integer.parseInt(st.nextToken());
        m = Integer.parseInt(st.nextToken());
        x = Integer.parseInt(st.nextToken());
        y = Integer.parseInt(st.nextToken());
        k = Integer.parseInt(st.nextToken()); // 명령 수행 횟수

        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());
            }
        }

        st = new StringTokenizer(br.readLine());
        for (int i = 0; i < k; i++) {
            int dir = Integer.parseInt(st.nextToken());
//            System.out.println("nextDir: " + dir);
            move(dir);
        }
    }

    // dir는 0~3
    public static void roll(int nextDir) {
        // 방향에 따라 굴렀을 때의 면의 숫자가 달라진다.
        int temp = dice[1];
        if (nextDir == 1) { // 동
            dice[1] = dice[4];
            dice[4] = dice[6];
            dice[6] = dice[3];
            dice[3] = temp;
        } else if (nextDir == 2) { // 서
            dice[1] = dice[3];
            dice[3] = dice[6];
            dice[6] = dice[4];
            dice[4] = temp;
        } else if (nextDir == 3) { // 북
            dice[1] = dice[5];
            dice[5] = dice[6];
            dice[6] = dice[2];
            dice[2] = temp;
        } else if (nextDir == 4) { // 남
            dice[1] = dice[2];
            dice[2] = dice[6];
            dice[6] = dice[5];
            dice[5] = temp;
        }
    }

    public static void move(int nextDir) {
        int nx = x + dx[nextDir];
        int ny = y + dy[nextDir];
//        System.out.println("coords: " + nx + " " + ny);

        // 범위를 넘어가면 명령을 무시한다.
        if (nx < 0 || nx >= n || ny < 0 || ny >= m) {
            return;
        }

        // 주사위가 다음 방향으로 구른다.
        roll(nextDir);

        // 굴렸을 때, 이동한 칸의 수가 0이면 주사위 바닥면에 있는 수가 복사된다.
        if (map[nx][ny] == 0) {
            map[nx][ny] = dice[6];
        } else {
            dice[6] = map[nx][ny];
            map[nx][ny] = 0;
        }

//        for (int i = 1; i <= 6; i++) {
//            System.out.print(dice[i] + " ");
//        }
//        System.out.println();

        // 주사위 윗면의 숫자를 출력한다.
        System.out.println(dice[1]);
        
        // 좌표를 갱신한다.
        x = nx;
        y = ny;
    }
}

 

저작자표시 비영리 동일조건 (새창열림)

'Problem Solving > BOJ' 카테고리의 다른 글

[BOJ/Java] 14888: 연산자 끼워넣기  (0) 2025.06.09
[BOJ/Java] 15683: 감시  (0) 2025.06.09
[BOJ/Java] 1463: 1로 만들기  (2) 2025.06.02
[BOJ/Java] 2225: 합분해  (1) 2025.05.26
[BOJ/Java] 1535: 안녕  (0) 2025.05.18
'Problem Solving/BOJ' 카테고리의 다른 글
  • [BOJ/Java] 14888: 연산자 끼워넣기
  • [BOJ/Java] 15683: 감시
  • [BOJ/Java] 1463: 1로 만들기
  • [BOJ/Java] 2225: 합분해
friend5hip
friend5hip
개발 관련 지식이나 기록을 남기고 있습니다.
  • friend5hip
    friend5hip
    friend5hip
  • 전체
    오늘
    어제
    • 분류 전체보기 (60)
      • 컴퓨터공학 (2)
        • 자료구조 (0)
        • 알고리즘 (1)
        • 데이터베이스 (1)
      • Problem Solving (42)
        • BOJ (25)
        • 프로그래머스 (15)
      • 언어 (2)
        • JavaScript (2)
      • 라이브러리 (12)
        • React (12)
      • 개발 (2)
      • 기타 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    N과 M
    그리디
    시뮬레이션
    백트래킹
    문자열
    집합
    dfs
    투 포인터
    구간 합
    소수 판별
    순열
    수학
    intersection observer
    삼성 sw 역량테스트
    정렬
    완전 탐색
    구현
    코드트리
    프로그래머스
    react
    누적 합
    백준
    vite
    BFS
    이분 탐색
    java
    맵
    dp
    JavaScript
    매개 변수 탐색
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
friend5hip
[BOJ/Java] 14499: 주사위 굴리기
상단으로

티스토리툴바