백준 14499번( 자바 )

topqr123q·2022년 1월 15일
0

Algorithm

목록 보기
27/36
post-thumbnail

구현

백준 14499번 구현 문제를 Java로 풀어보았다. 초반에 주사위의 6개 면을 어떻게 표현해야할지, 주사위가 구를 때 각 면의 위치가 바뀌는 것을 어떻게 표현해야할지 고민을 하느라 시간을 좀 날렸다.
주사위 객체를 주어진 특성에 맞게 선언해주면 쉽게 해결이 가능하다.

문제가 역시 길기에 링크만 첨부한다.
https://www.acmicpc.net/problem/14499


주사위 구현

주사위의 6개 면을 서로 다른 이름을 주어 네이밍을 하고 주사위가 구르는 행위를 하나의 메소드로서 선언해줬다.
윗면을 top, 바닥면을 bottom, 왼쪽을 left, 오른쪽을 right, 뒷쪽면을 rear, 정면을 front라 이름 지었다.

static class Dice {
        int top, bottom, rear, front, left, right;

        Dice(){ // 주사위 초기 상태
            top = 0; bottom = 0; rear = 0; front = 0; left = 0; right = 0;
        }

        void move1(){ // 1번 굴리기, rear&front 은 그대로
            int beforeTop = top; int beforeBottom = bottom; int beforeLeft = left; int beforeRight = right;
            top = beforeLeft; left = beforeBottom; bottom = beforeRight; right = beforeTop;
        }

        void move2(){ // 2번 굴리기, rear&front 은 그대로
            int beforeTop = top; int beforeBottom = bottom; int beforeLeft = left; int beforeRight = right;
            top = beforeRight; right = beforeBottom; bottom = beforeLeft; left = beforeTop;
        }

        void move3(){ // 3번 굴리기, left&right 는 그대로
            int beforeTop = top; int beforeBottom = bottom; int beforeRear = rear; int beforeFront = front;
            top = beforeFront; front = beforeBottom; bottom = beforeRear; rear = beforeTop;
        }

        void move4(){ // 4번 굴리기, left&right 는 그대로
            int beforeTop = top; int beforeBottom = bottom; int beforeRear = rear; int beforeFront = front;
            top = beforeRear; front = beforeTop; bottom = beforeFront; rear = beforeBottom;
        }
    }

문제에 주어진 1,2,3,4 번 움직임에 따라 어느 면이 어느 위치로 이동하는지를 move1,2,3,4 메소드로 구현했다.


무시해야 하는 move

만약 map의 범위를 벗어나는 move를 하게 될 때는 무시해야 한다. 따라서 무작정 move를 해줄 게 아니라 범위를 먼저 확인한 후에 움직임을 가져야 한다.
이를 위해 범위를 확인한 후에 1. 주사위를 굴리고, 2. 윗면을 출력한다.

int whereToMove = orders[i];
            int tmpX = x + moveDirection[whereToMove-1][0];
            int tmpY = y + moveDirection[whereToMove-1][1];

            if(isInRange(tmpX, tmpY)){
                x = tmpX;   y = tmpY;

                switch(whereToMove){
                    case 1:
                        dice.move1();
                        break;
                    case 2:
                        dice.move2();
                        break;
                    case 3:
                        dice.move3();
                        break;
                    case 4:
                        dice.move4();
                        break;
                    default:
                        break;
                }

                if(map[x][y]==0){ // 지도가 0이면
                    map[x][y] = dice.bottom;
                }
                else{ // 지도가 0이 아니면
                    dice.bottom = map[x][y];
                    map[x][y] = 0;
                }

                bfw.write(String.valueOf(dice.top) + "\n");
            }

이렇게 범위를 확인해주게 되면 움직일 수 없을 경우에는 move 명령을 무시하고 그냥 지나치게 된다.


아래는 내가 제출한 코드다.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.util.StringTokenizer;

public class boj14499 {
    static int n,m,x,y,k;
    static int[][] map;
    static int[] orders;
    static int[][] moveDirection = { {0,1}, {0,-1}, {-1,0}, {1,0} };

    public static void main(String args[]) throws IOException {
        BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer stk = new StringTokenizer(bfr.readLine());
        n = Integer.parseInt(stk.nextToken()); m = Integer.parseInt(stk.nextToken());
        x = Integer.parseInt(stk.nextToken()); y = Integer.parseInt(stk.nextToken());
        k = Integer.parseInt(stk.nextToken());

        map = new int[n][m];
        for(int i=0; i<n; i++){ // 지도 입력
            stk = new StringTokenizer(bfr.readLine());
            for(int j=0; j<m; j++)
                map[i][j] = Integer.parseInt(stk.nextToken());
        }
        orders = new int[k];
        stk = new StringTokenizer(bfr.readLine());
        for(int i=0; i<k; i++) // 명령 입력
            orders[i] = Integer.parseInt(stk.nextToken());


        Dice dice = new Dice();
        for(int i=0; i<k; i++){
            int whereToMove = orders[i];
            int tmpX = x + moveDirection[whereToMove-1][0];
            int tmpY = y + moveDirection[whereToMove-1][1];

            if(isInRange(tmpX, tmpY)){
                x = tmpX;   y = tmpY;

                switch(whereToMove){
                    case 1:
                        dice.move1();
                        break;
                    case 2:
                        dice.move2();
                        break;
                    case 3:
                        dice.move3();
                        break;
                    case 4:
                        dice.move4();
                        break;
                    default:
                        break;
                }

                if(map[x][y]==0){ // 지도가 0이면
                    map[x][y] = dice.bottom;
                }
                else{ // 지도가 0이 아니면
                    dice.bottom = map[x][y];
                    map[x][y] = 0;
                }

                bfw.write(String.valueOf(dice.top) + "\n");
            }
        }
        bfw.close();
    }

    static class Dice {
        int top, bottom, rear, front, left, right;

        Dice(){
            top = 0; bottom = 0; rear = 0; front = 0; left = 0; right = 0;
        }

        void move1(){ // 1번 굴리기, rear&front 은 그대로
            int beforeTop = top; int beforeBottom = bottom; int beforeLeft = left; int beforeRight = right;
            top = beforeLeft; left = beforeBottom; bottom = beforeRight; right = beforeTop;
        }

        void move2(){ // 2번 굴리기, rear&front 은 그대로
            int beforeTop = top; int beforeBottom = bottom; int beforeLeft = left; int beforeRight = right;
            top = beforeRight; right = beforeBottom; bottom = beforeLeft; left = beforeTop;
        }

        void move3(){ // 3번 굴리기, left&right 는 그대로
            int beforeTop = top; int beforeBottom = bottom; int beforeRear = rear; int beforeFront = front;
            top = beforeFront; front = beforeBottom; bottom = beforeRear; rear = beforeTop;
        }

        void move4(){ // 4번 굴리기, left&right 는 그대로
            int beforeTop = top; int beforeBottom = bottom; int beforeRear = rear; int beforeFront = front;
            top = beforeRear; front = beforeTop; bottom = beforeFront; rear = beforeBottom;
        }
    }

    static Boolean isInRange(int x, int y){
        if(0<=x && x<n && 0<=y && y<m)  return true;
        else    return false;
    }
}


처음에 ArrayIndexOutOfBounds를 만난 이유는 map의 범위에 맞는 움직임인지 확인해주지 않아 범위를 벗어나게 되어 발생했다. 문제가 길다보니 놓칠 때가 많다.

profile
개발 빼고 다 하는 개발자

0개의 댓글