ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 23288
    Java/코딩테스트 2023. 10. 13. 20:04

    🎲 백준 23288 주사위 굴리기 2

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

     

    23288번: 주사위 굴리기 2

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

    www.acmicpc.net

    🎲 어릴때부터 이런 입체도형 계산하는 문제를 유구하게 못했는데 ..주사위 돌아가는거 생각하는게 헷갈렸다ㅎ 

    🎲 주사위 돌아가는 부분을 이 블로그를 보고 힌트를 얻었다.

     

    🎲 주사위

    🎲 주사위 자체를 현재 방향에 따라 위 이미지처럼 계속 돌려가면서, 아랫면 (dice[3][1]) 만 점수 비교하는데 쓰면 된다. 

     

    🎲 자료구조

    private static int row, col, move, answer, currentDir;
    private static Pos curPos;
    private static int[] dirX = { 0, 1, 0, -1};
    private static int[] dirY = { 1, 0, -1, 0};
    private static int[][] dice = {
            {0, 2, 0},
            {4, 1, 3},
            {0, 5, 0},
            {0, 6, 0}
    };
    private static int[][] map;

    🎲 메인 로직

    🎲 firstMove : 현재 위치에서 방향 결정한 다음 이동.

    • nextX, nextY 찾아서 이동시키고, 방향(currentDir)도 유효하지 않은 방향이면 뒤집어주기 
    • 그 후, nextX, nextY 기준으로 getScore(), findNextDir() 호출하기 
    private static void firstMove() {
        int nextX = curPos.x + dirX[currentDir];
        int nextY = curPos.y + dirY[currentDir];
    
        if (!isValid(nextX, nextY)) {
            nextX = curPos.x + dirX[(currentDir + 2) % 4];
            nextY = curPos.y + dirY[(currentDir + 2) % 4];
            currentDir = (currentDir + 2) % 4;
        }
    
        curPos = new Pos(nextX, nextY);
        getScore(nextX, nextY);
        findNextDir(nextX, nextY);
    }

     

     

    🎲 getScore() : 해당 좌표의 점수, 그리고 findLen 함수 호출을 통해 갈 수 있는 칸 수 계산한다음 해당 칸에서의 점수 계산하기

    private static void getScore(int x, int y) {
        int score = map[x][y];
        int len = findLen(x, y, score);
        answer += score * len;
    }

     

    🎲 findLen() : BFS 방식 구현

    • 헷갈렸던게 갈 수 있는 경로라고 생각했는데, 이동할 수 있는 칸의 개수를 세는 것이다. 
    • 경로라 생각하고 DFS로 하면 중간 테스트 케이스 틀리는 게 생긴다. 
    • 종단점이 있는게 아니고 연결된 블록 찾는거라 BFS가 문제 취지에 더 맞을 것 같다. 
    private static int findLen(int x, int y, int score) {
        boolean[][] temp = new boolean[row][col];
        int len = 0;
        Queue<Pos> queue = new LinkedList<>();
        queue.add(new Pos(x, y));
        temp[x][y] = true;
    
        while (!queue.isEmpty()) {
            Pos pop = queue.poll();
            len++;
            for (int i = 0; i < 4; i++) {
                int nextX = pop.x + dirX[i];
                int nextY = pop.y + dirY[i];
    
                if (!isValid(nextX, nextY)) {
                    continue;
                }
    
                if (map[nextX][nextY] != score) {
                    continue;
                }
    
                if (temp[nextX][nextY]) {
                    continue;
                }
    
                queue.add(new Pos(nextX, nextY));
                temp[nextX][nextY] = true;
            }
        }
        return len;
    }

     

     

    🎲 findNextDir() : 다음 방향을 찾는다. 

    • 여기서 맨 처음 그린 주사위 계산 작업이 나온다. 
    • 현재 방향에 맞게 주사위 아랫면을 계산해주고, map에 있는 score와 비교하여 방향을 재조정해준다. 
    private static void findNextDir(int x, int y) {
        // 현재 주사위 아랫면 구하기
        switch (currentDir) {
            case 0 :
                int temp = dice[1][2];
                dice[1][2] = dice[1][1];
                dice[1][1] = dice[1][0];
                dice[1][0] = dice[3][1];
                dice[3][1] = temp;
                break;
            case 1 :
                temp = dice[3][1];
                dice[3][1] = dice[2][1];
                dice[2][1] = dice[1][1];
                dice[1][1] = dice[0][1];
                dice[0][1] = temp;
                break;
            case 2 :
                temp = dice[1][0];
                dice[1][0] = dice[1][1];
                dice[1][1] = dice[1][2];
                dice[1][2] = dice[3][1];
                dice[3][1] = temp;
                break;
            case 3 :
                temp = dice[0][1];
                dice[0][1] = dice[1][1];
                dice[1][1] = dice[2][1];
                dice[2][1] = dice[3][1];
                dice[3][1] = temp;
                break;
        }
    
        int a = dice[3][1];
        if (a > map[x][y]) {
            currentDir = (currentDir + 1) % 4;
        } else if (a < map[x][y]) {
            currentDir = (currentDir + 3) % 4;
        }
    }

     


     

    🎲 전체코드 

    import java.util.*;
    import java.io.*;
    public class p23288 {
        private static int row, col, move, answer, currentDir;
        private static Pos curPos;
        private static int[] dirX = { 0, 1, 0, -1};
        private static int[] dirY = { 1, 0, -1, 0};
        private static int[][] dice = {
                {0, 2, 0},
                {4, 1, 3},
                {0, 5, 0},
                {0, 6, 0}
        };
        private static int[][] map;
        public static void main(String[] args) throws IOException {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            StringTokenizer st = new StringTokenizer(br.readLine());
    
            row = Integer.parseInt(st.nextToken());
            col = Integer.parseInt(st.nextToken());
            move = Integer.parseInt(st.nextToken());
            answer = currentDir = 0;
    
            map = new int[row][col];
            for (int i = 0; i < row; i++) {
                st = new StringTokenizer(br.readLine());
                for (int j = 0; j < col; j++) {
                    map[i][j] = Integer.parseInt(st.nextToken());
                }
            }
    
            curPos = new Pos(0,0 );
            for (int i = 0; i < move; i++) {
                firstMove();
            }
            System.out.println(answer);
        }
    
        private static void firstMove() {
            int nextX = curPos.x + dirX[currentDir];
            int nextY = curPos.y + dirY[currentDir];
    
            if (!isValid(nextX, nextY)) {
                nextX = curPos.x + dirX[(currentDir + 2) % 4];
                nextY = curPos.y + dirY[(currentDir + 2) % 4];
                currentDir = (currentDir + 2) % 4;
            }
    
            curPos = new Pos(nextX, nextY);
            getScore(nextX, nextY);
            findNextDir(nextX, nextY);
        }
    
        private static void findNextDir(int x, int y) {
            // 현재 주사위 아랫면 구하기
            switch (currentDir) {
                case 0 :
                    int temp = dice[1][2];
                    dice[1][2] = dice[1][1];
                    dice[1][1] = dice[1][0];
                    dice[1][0] = dice[3][1];
                    dice[3][1] = temp;
                    break;
                case 1 :
                    temp = dice[3][1];
                    dice[3][1] = dice[2][1];
                    dice[2][1] = dice[1][1];
                    dice[1][1] = dice[0][1];
                    dice[0][1] = temp;
                    break;
                case 2 :
                    temp = dice[1][0];
                    dice[1][0] = dice[1][1];
                    dice[1][1] = dice[1][2];
                    dice[1][2] = dice[3][1];
                    dice[3][1] = temp;
                    break;
                case 3 :
                    temp = dice[0][1];
                    dice[0][1] = dice[1][1];
                    dice[1][1] = dice[2][1];
                    dice[2][1] = dice[3][1];
                    dice[3][1] = temp;
                    break;
            }
    
            int a = dice[3][1];
            if (a > map[x][y]) {
                currentDir = (currentDir + 1) % 4;
            } else if (a < map[x][y]) {
                currentDir = (currentDir + 3) % 4;
            }
        }
    
        private static void getScore(int x, int y) {
            int score = map[x][y];
            int len = findLen(x, y, score);
            answer += score * len;
        }
    
        private static int findLen(int x, int y, int score) {
            boolean[][] temp = new boolean[row][col];
            int len = 0;
            Queue<Pos> queue = new LinkedList<>();
            queue.add(new Pos(x, y));
            temp[x][y] = true;
    
            while (!queue.isEmpty()) {
                Pos pop = queue.poll();
                len++;
                for (int i = 0; i < 4; i++) {
                    int nextX = pop.x + dirX[i];
                    int nextY = pop.y + dirY[i];
    
                    if (!isValid(nextX, nextY)) {
                        continue;
                    }
    
                    if (map[nextX][nextY] != score) {
                        continue;
                    }
    
                    if (temp[nextX][nextY]) {
                        continue;
                    }
    
                    queue.add(new Pos(nextX, nextY));
                    temp[nextX][nextY] = true;
                }
            }
            return len;
        }
    
        private static boolean isValid(int x, int y) {
            if (x < 0 || x >= row || y < 0 || y >= col) {
                return false;
            }
            return true;
        }
    
        private static class Pos {
            int x;
            int y;
            Pos (int x, int y) {
                this.x = x;
                this.y = y;
            }
        }
    }
    

    'Java > 코딩테스트' 카테고리의 다른 글

    프로그래머스 - 입국심사, 징검다리  (0) 2023.10.24
    프로그래머스 - 호텔 대실, 뒤에 있는 큰 수 찾기, 주차 요금 계산  (0) 2023.10.22
    백준 20055  (0) 2023.10.13
    백준 19237  (0) 2023.10.12
    백준 20057  (0) 2023.10.12
Designed by Tistory.