본문 바로가기
문제풀이/백준

[JAVA] BOJ 백준 23288번 - 주사위 굴리기 2

by 그적 2024. 2. 5.

목차

  • 문제
  • 내가 푼 방법
  • 자바 코드
  • 결과 및 회고

1. 문제

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

 

23288번: 주사위 굴리기 2

크기가 N×M인 지도가 존재한다. 지도의 오른쪽은 동쪽, 위쪽은 북쪽이다. 지도의 좌표는 (r, c)로 나타내며, r는 북쪽으로부터 떨어진 칸의 개수, c는 서쪽으로부터 떨어진 칸의 개수이다. 가장 왼

www.acmicpc.net


2. 내가 푼 방법

실수만 안 하면 금방 풀리는 빡구현 문제이다.

 

우선 서/북/동/남 순서로 방향을 설정했는데, 시계 방향 회전은 (dir + 1) % 4, 반시계 방향 회전은 (dir + 3) % 4, 반대 방향은 (dir + 2) % 4를 작성하여 코드를 간결하게 해주었다.

 

주사위를 굴리는 기능인 roll() 함수, 점수를 획득하는 기능인 getScore() 함수, 다음 방향을 계산하는 calculateDir() 함수로 구분했으며, 점수 획득하는 기능에서 BFS 알고리즘을 이용하는 것 외에는 인덱스랑 이동 위치만 실수하지 않으면 된다.

public static void solution() {
    while (K-- > 0) {
        roll();
        getScore();
        calculateDir();
    }
}

public static void calculateDir() {
    int A = dice[3][1];
    int B = arr[sx][sy];

    if (A > B) {
        dir = (dir + 1) % 4;
    }
    else if (A < B) {
        dir = (dir + 3) % 4;
    }
}

public static void getScore() {
    Queue<int[]> queue = new ArrayDeque<>();
    boolean[][] visit = new boolean[N][M];

    int cnt = 1;
    visit[sx][sy] = true;
    queue.add(new int[]{sx, sy});

    while (!queue.isEmpty()) {
        int[] q = queue.poll();
        int x = q[0];
        int y = q[1];

        for (int d = 0; d < dx.length; d++) {
            int nx = x + dx[d];
            int ny = y + dy[d];

            if (nx < 0 || ny < 0 || nx >= N || ny >= M) continue;
            if (visit[nx][ny] || arr[nx][ny] != arr[sx][sy]) continue;

            cnt++;
            visit[nx][ny] = true;
            queue.add(new int[]{nx, ny});
        }
    }

    result += (cnt * arr[sx][sy]);
}

public static void roll() {
    int nx = sx + dx[dir];
    int ny = sy + dy[dir];

    if (nx < 0 || ny < 0 || nx >= N || ny >= M) {
        dir = (dir + 2) % 4;
        nx = sx + dx[dir];
        ny = sy + dy[dir];
    }

    sx = nx;
    sy = ny;
    rollDice();
}

public static void rollDice() {
    if (dir == 0) {
        int tmp = dice[1][1];
        dice[1][1] = dice[1][2];
        dice[1][2] = dice[3][1];
        dice[3][1] = dice[1][0];
        dice[1][0] = tmp;
    }
    else if (dir == 1) {
        int tmp = dice[0][1];
        dice[0][1] = dice[1][1];
        dice[1][1] = dice[2][1];
        dice[2][1] = dice[3][1];
        dice[3][1] = tmp;
    }
    else if (dir == 2) {
        int tmp = dice[1][1];
        dice[1][1] = dice[1][0];
        dice[1][0] = dice[3][1];
        dice[3][1] = dice[1][2];
        dice[1][2] = tmp;
    }
    else {
        int tmp = dice[3][1];
        dice[3][1] = dice[2][1];
        dice[2][1] = dice[1][1];
        dice[1][1] = dice[0][1];
        dice[0][1] = tmp;
    }
}

3. 자바 코드

깃허브 풀이 주소 : https://github.com/geujeog/BOJ/blob/main/B23288.java

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

class Main {
    static int[] dx = {0, -1, 0, 1};
    static int[] dy = {-1, 0, 1, 0};

    static int N, M, K;
    static int[][] arr;
    static int sx, sy, dir;
    static int[][] dice;
    static int result;

    public static void main (String[] args) throws IOException {
        input();
        solution();
        output();
    }

    public static void solution() {
        while (K-- > 0) {
            roll();
            getScore();
            calculateDir();
        }
    }

    public static void calculateDir() {
        int A = dice[3][1];
        int B = arr[sx][sy];

        if (A > B) {
            dir = (dir + 1) % 4;
        }
        else if (A < B) {
            dir = (dir + 3) % 4;
        }
    }

    public static void getScore() {
        Queue<int[]> queue = new ArrayDeque<>();
        boolean[][] visit = new boolean[N][M];

        int cnt = 1;
        visit[sx][sy] = true;
        queue.add(new int[]{sx, sy});

        while (!queue.isEmpty()) {
            int[] q = queue.poll();
            int x = q[0];
            int y = q[1];

            for (int d = 0; d < dx.length; d++) {
                int nx = x + dx[d];
                int ny = y + dy[d];

                if (nx < 0 || ny < 0 || nx >= N || ny >= M) continue;
                if (visit[nx][ny] || arr[nx][ny] != arr[sx][sy]) continue;

                cnt++;
                visit[nx][ny] = true;
                queue.add(new int[]{nx, ny});
            }
        }

        result += (cnt * arr[sx][sy]);
    }

    public static void roll() {
        int nx = sx + dx[dir];
        int ny = sy + dy[dir];

        if (nx < 0 || ny < 0 || nx >= N || ny >= M) {
            dir = (dir + 2) % 4;
            nx = sx + dx[dir];
            ny = sy + dy[dir];
        }

        sx = nx;
        sy = ny;
        rollDice();
    }

    public static void rollDice() {
        if (dir == 0) {
            int tmp = dice[1][1];
            dice[1][1] = dice[1][2];
            dice[1][2] = dice[3][1];
            dice[3][1] = dice[1][0];
            dice[1][0] = tmp;
        }
        else if (dir == 1) {
            int tmp = dice[0][1];
            dice[0][1] = dice[1][1];
            dice[1][1] = dice[2][1];
            dice[2][1] = dice[3][1];
            dice[3][1] = tmp;
        }
        else if (dir == 2) {
            int tmp = dice[1][1];
            dice[1][1] = dice[1][0];
            dice[1][0] = dice[3][1];
            dice[3][1] = dice[1][2];
            dice[1][2] = tmp;
        }
        else {
            int tmp = dice[3][1];
            dice[3][1] = dice[2][1];
            dice[2][1] = dice[1][1];
            dice[1][1] = dice[0][1];
            dice[0][1] = tmp;
        }
    }

    public static void output() throws IOException {
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        bw.write(result+"");

        bw.flush();
        bw.close();
    }

    public static void input() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());
        arr = new int[N][M];
        sx = sy = 0;
        dir = 2;
        dice = new int[4][3];

        dice[1][1] = 1;
        dice[0][1] = 2;
        dice[1][0] = 4;
        dice[1][2] = 3;
        dice[2][1] = 5;
        dice[3][1] = 6;

        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < M; j++) {
                arr[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        br.close();
    }
}

 


4. 결과 및 회고

이번 문제는 한 번에 실수 없이 풀었다. 풀고 나니 주사위를 이동시키는 부분을 너무 하드코딩했나 싶은데,, 코테 풀 땐 저게 직관적이어서 저렇게 풀 거 같단 말이지

 

댓글