Develope Story

2019-03-26 [JAVA]백준 1520번 - 내리막 길

|

문제출처

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

문제

여행을 떠난 세준이는 지도를 하나 구하였다. 이 지도는 아래 그림과 같이 직사각형 모양이며 여러 칸으로 나뉘어져 있다. 한 칸은 한 지점을 나타내는데 각 칸에는 그 지점의 높이가 쓰여 있으며, 각 지점 사이의 이동은 지도에서 상하좌우 이웃한 곳끼리만 가능하다.

img

현재 제일 왼쪽 위 칸이 나타내는 지점에 있는 세준이는 제일 오른쪽 아래 칸이 나타내는 지점으로 가려고 한다. 그런데 가능한 힘을 적게 들이고 싶어 항상 높이가 더 낮은 지점으로만 이동하여 목표 지점까지 가고자 한다. 위와 같은 지도에서는 다음과 같은 세 가지 경로가 가능하다.

img

img

지도가 주어질 때 이와 같이 제일 왼쪽 위 지점에서 출발하여 제일 오른쪽 아래 지점까지 항상 내리막길로만 이동하는 경로의 개수를 구하는 프로그램을 작성하시오.

문제 접근 방법 1 (실패 - 메모리 초과)

  • bfs를 이용하여 자기 자리 보다 수치가 작은 곳으로 이동하여 총 경로 수 체크
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class Baekjoon_1520 {
    static way[][] map;
    static int[] x = {-1, 0, 1, 0};
    static int[] y = {0, 1, 0, -1};
    static int n, m;
    static int count = 0;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        n = sc.nextInt();
        m = sc.nextInt();
        map = new way[n][m];

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                map[i][j] = new way(j, i, sc.nextInt());
            }
        }
        //0,0에서 시작
        bfs(map[0][0]);

        System.out.println(count);
    }
    //bfs
    public static void bfs(way w) {
        Queue<way> q = new LinkedList<>();
        q.offer(w);

        while (!q.isEmpty()) {
            way tmp = q.poll();

            for (int i = 0; i < 4; i++) {
                int wx = tmp.x + x[i];
                int wy = tmp.y + y[i];

                if (wx >= 0 && wy >= 0 && wx < m && wy < n) {
                    if (map[wy][wx].value < map[tmp.y][tmp.x].value) {
                        q.offer(map[wy][wx]);
                        //도착했을때
                        if (wy == n - 1 && wx == m - 1)
                            count++;
                    }
                }
            }
        }
    }
}

class way {
    int x, y;
    int value;

    way(int x, int y, int value) {
        this.x = x;
        this.y = y;
        this.value = value;
    }
}

문제접근 방법2 (DFS)

=> m-1, n-1부터 dfs로 추적


import java.util.Scanner;

public class Baekjoon_1520 {
    static int[][] map, dp;
    static int n, m;
    static int[] wx = {-1, 0, 1, 0};
    static int[] wy = {0, -1, 0, 1};

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        n = sc.nextInt();
        m = sc.nextInt();
        map = new int[n][m];
        dp = new int[n][m];

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                map[i][j] = sc.nextInt();
            }
        }

        System.out.println(dfs(m-1, n-1));
    }

    public static int dfs(int x, int y) {
        if (x == 0 && y == 0)
            return 1;

        if (dp[y][x] == 0) {
            for (int i = 0; i < 4; i++) {
                int ny = y + wy[i];
                int nx = x + wx[i];
                if (nx >= 0 && ny >= 0 && nx < m && ny < n) {
                    if (map[ny][nx] > map[y][x]) {
                        dp[y][x] += dfs(nx, ny);
                    }
                }
            }
        }
        return dp[y][x];
    }
}

=> 시간초과

  • dp값을 -1로 선언해주어 방문시 0으로 바꾸면서 체크 (참고. https://mygumi.tistory.com/231)

import java.util.Scanner;

public class Baekjoon_1520 {
    static int[][] map, dp;
    static int n, m;
    static int[] wx = {-1, 0, 1, 0};
    static int[] wy = {0, -1, 0, 1};

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        n = sc.nextInt();
        m = sc.nextInt();
        map = new int[n][m];
        dp = new int[n][m];

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                map[i][j] = sc.nextInt();
                dp[i][j] = -1; //dp를 -1로 초기화
            }
        }

        System.out.println(dfs(m-1, n-1));
    }

    public static int dfs(int x, int y) {
        if (x == 0 && y == 0)
            return 1;

        if (dp[y][x] == -1) {
            dp[y][x] = 0; //방문시 0으로 체크
            for (int i = 0; i < 4; i++) {
                int ny = y + wy[i];
                int nx = x + wx[i];
                if (nx >= 0 && ny >= 0 && nx < m && ny < n) {
                    if (map[ny][nx] > map[y][x]) {
                        dp[y][x] += dfs(nx, ny);
                    }
                }
            }
        }
        return dp[y][x];
    }
}
  • 내리막기로 갈수 있는 경우의 수 = 도착지점으로 부터 시작지점까지 오르막기 경우의 수
  • dp값을 -1로 초기화 하여 방문시 0으로 변경하는 방식으로 방문 체크

2019-03-21 [JAVA] 백준 9465번-스티커

|

문제 출처

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

문제

상근이의 여동생 상냥이는 문방구에서 스티커 2n개를 구매했다. 스티커는 그림 (a)와 같이 2행 n열로 배치되어 있다. 상냥이는 스티커를 이용해 책상을 꾸미려고 한다.

상냥이가 구매한 스티커의 품질은 매우 좋지 않다. 스티커 한 장을 떼면, 그 스티커와 변을 공유하는 스티커는 모두 찢어져서 사용할 수 없게 된다. 즉, 뗀 스티커의 왼쪽, 오른쪽, 위, 아래에 있는 스티커는 사용할 수 없게 된다.

img

모든 스티커를 붙일 수 없게된 상냥이는 각 스티커에 점수를 매기고, 점수의 합이 최대가 되게 스티커를 떼어내려고 한다. 먼저, 그림 (b)와 같이 각 스티커에 점수를 매겼다. 상냥이가 뗄 수 있는 스티커의 점수의 최댓값을 구하는 프로그램을 작성하시오. 즉, 2n개의 스티커 중에서 점수의 합이 최대가 되면서 서로 변을 공유 하지 않는 스티커 집합을 구해야 한다.

위의 그림의 경우에 점수가 50, 50, 100, 60인 스티커를 고르면, 점수는 260이 되고 이 것이 최대 점수이다. 가장 높은 점수를 가지는 두 스티커 (100과 70)은 변을 공유하기 때문에, 동시에 뗄 수 없다.

입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스의 첫째 줄에는 n (1 ≤ n ≤ 100,000)이 주어진다. 다음 두 줄에는 n개의 정수가 주어지며, 각 정수는 그 위치에 해당하는 스티커의 점수이다. 연속하는 두 정수 사이에는 빈 칸이 하나 있다. 점수는 0보다 크거나 같고, 100보다 작거나 같은 정수이다.

출력

각 테스트 케이스 마다, 2n개의 스티커 중에서 두 변을 공유하지 않는 스티커 점수의 최댓값을 출력한다.

문제 풀이

  Sticker[][1] sticker[][2] sticker[][3] sticker[][4] sticker[][5]
sticker[0][] 50 10 100 20 40
sticker[1][] 30 50 70 10 60
  • 같은 행에 있는 스티커가 연속으로 선택 될 수 없다. 0 -> 1 -> 0 행이거나 0 -> (공백) -> 1 행

  • dp를 0과 1 두가지 행을 구분하여 구한다. (dp [a][b]는 a행 b열을 반드시 포함한 b열까지의 합의 최댓값 )

    • 처음 초기 dp 설정
                dp[0][1] = sticker[0][1]; //50
                dp[1][1] = sticker[1][1]; //30
                dp[0][2] = sticker[1][1] + sticker[0][2]; //50 + 50
                dp[1][2] = sticker[0][1] + sticker[1][2]; //30 + 10
    
    • dp식 구성
    for (int i = 3; i <= n; i++) { //0 -> 1 -> 0 행이거나 0 -> (공백) -> 1 행 중 최대
                    dp[0][i] = Math.max(dp[1][i - 1], dp[1][i - 2]) + sticker[0][i];
                    dp[1][i] = Math.max(dp[0][i - 2], dp[0][i - 1]) + sticker[1][i];
                }
    
  • 출력

    System.out.println(Math.max(dp[0][n], dp[1][n])); //0행과 1행 중 최댓값 출력
    

전체 소스

import java.util.Scanner;

public class Baekjoon_9465 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int t = sc.nextInt();
        for (int k = 0; k < t; k++) {
            int n = sc.nextInt();

            int[][] dp = new int[2][n + 1];
            int[][] sticker = new int[2][n + 1];

            for (int i = 1; i <= n; i++)
                sticker[0][i] = sc.nextInt();

            for (int i = 1; i <= n; i++)
                sticker[1][i] = sc.nextInt();
            //dp[1], dp[2] 설
            dp[0][1] = sticker[0][1];
            dp[1][1] = sticker[1][1];
            dp[0][2] = sticker[1][1] + sticker[0][2];
            dp[1][2] = sticker[0][1] + sticker[1][2];


            for (int i = 3; i <= n; i++) {
                dp[0][i] = Math.max(dp[1][i - 1], dp[1][i - 2]) + sticker[0][i];
                dp[1][i] = Math.max(dp[0][i - 2], dp[0][i - 1]) + sticker[1][i];
            }

            System.out.println(Math.max(dp[0][n], dp[1][n]));
        }
    }
}

2019-03-21 [JAVA]백준 1986번 - 체스

|

백준 1986 : 체스

문제출처

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

문제

문제

n*m 크기의 체스 판과, 상대팀의 Queen, Knight, Pawn의 위치가 주어져 있을 때, 안전한 칸이 몇 칸인지 세는 프로그램을 작성하시오. (안전한 칸이란 말은 그 곳에 자신의 말이 있어도 잡힐 가능성이 없다는 것이다.)

참고로 Queen은 가로, 세로, 대각선으로 갈 수 있는 만큼 최대한 많이 이동을 할 수 있는데 만약 그 중간에 장애물이 있다면 이동을 할 수 없다. 그리고 Knight는 2*3 직사각형을 그렸을 때, 반대쪽 꼭짓점으로 이동을 할 수 있다. 아래 그림과 같은 8칸이 이에 해당한다.

img

이때 Knight는 중간에 장애물이 있더라도 이동을 할 수 있다. 그리고 Pawn은 상대팀의 말은 잡을 수 없다고 하자(즉, 장애물의 역할만 한다는 것이다).

예를 들어 다음과 같이 말이 배치가 되어 있다면 진하게 표시된 부분이 안전한 칸이 될 것이다. (K : Knight, Q : Queen, P : Pawn)

img

입력

첫째 줄에는 체스 판의 크기 n과 m이 주어진다. (1<=n, m<=1000) 그리고 둘째 줄에는 Queen의 개수와 그 개수만큼의 Queen의 위치가 입력된다. 그리고 마찬가지로 셋째 줄에는 Knight의 개수와 위치, 넷째 줄에는 Pawn의 개수와 위치가 입력된다. (즉 둘째 줄~ 넷째 줄은 k,r1,c1,r2,c2,…,rk,ck 이 빈칸을 사이에 두고 주어진다는 것이다. 여기서 ri는 i번째 말의 행 위치, ci는 i번째 말의 열 위치를 의미한다.) 한 칸에는 하나의 말만 놓인다고 가정한다. Knight, Queen, Pawn의 개수는 각각 100을 넘지 않는다.

출력

첫째 줄에 n*m 체스판에 안전한 칸이 몇 칸인지 출력하시오.

예제 입력 1 복사

4 4
2 1 4 2 4
1 1 2
1 2 3

문제 풀이

  1. 체스판에서 Queen, Knight, Pawn의 위치를 지정

  2. Queen과 Knight 이동

    • Queen
      • 자기 위치를 기준으로 상하좌우 대각선으로 직진 (장애물이 있을시 이동 중단)1

      • Queen의 위치를 0,0 이라 가정하여 x, y좌표로 나누어 배열로 선언

      static int[] Queen_X = {-1, -1, 0, 1, 1, 1, 0, -1};
      static int[] Queen_Y = {0, 1, 1, 1, 0, -1, -1, -1}
      
      • Queen가 이동할수 있으면 -1
          public static void Queen(int x, int y) {
              for (int i = 0; i < 8; i++) {
                  int queenX = x + Queen_X[i];
                  int queenY = y + Queen_Y[i];
           
                  while (queenX >= 0 && queenX < M && queenY < N && queenY >= 0 && chessBoard[queenY][queenX] <= 0) {
                      chessBoard[queenY][queenX] = -1;//Queen 이동 경로 체크
                      queenX += Queen_X[i];
                      queenY += Queen_Y[i];
                  }
              }
          }
      
    • Knight

      • 자기 위치를 기준으로 2*3직사각형을 그려 반대쪽 꼭짓점

        img

      • Knight의 위치를 0,0 이라 가정하여 x, y좌표로 나누어 배열로 선언

        static int[] Knight_X = {-2, -1, 1, 2, 2, 1, -1, -2};
        static int[] Knight_Y = {1, 2, 2, 1, -1, -2, -2, -1};
        
      • Knight가 이동할수 있으면 -1

          public static void Knight(int x, int y) {
              for (int i = 0; i < 8; i++) {
                  int knightX = x + Knight_X[i];
                  int knightY = y + Knight_Y[i];
           
                  if (knightX >= 0 && knightX < M && knightY < N && knightY >= 0)
                      if (chessBoard[knightY][knightX] == 0)//Knight 이동 경로 체크
                          chessBoard[knightY][knightX] = -1;
              }
          }
      
  3. 안전한 칸 개수 세기

            for (int i = 0; i < N; i++)
                for (int j = 0; j < M; j++)
                    if (chessBoard[i][j] == 0)//체스판이 0이면 Knight나 Queen의 이동 경로에 없다.
                        count++;
    

전체 소스

import java.util.Scanner;

public class Baekjoon_1986 {
    static int[] Knight_X = {-2, -1, 1, 2, 2, 1, -1, -2};
    static int[] Knight_Y = {1, 2, 2, 1, -1, -2, -2, -1};
    static int[] Queen_X = {-1, -1, 0, 1, 1, 1, 0, -1};
    static int[] Queen_Y = {0, 1, 1, 1, 0, -1, -1, -1};
    static int N, M;
    static int[][] chessBoard;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        N = sc.nextInt();
        M = sc.nextInt();
        int count = 0;
        chessBoard = new int[N][M]; // 체스판 1: queen 2: knight 3: pawn 위치

        int k = sc.nextInt();
        for (int i = 0; i < k; i++)
            chessBoard[sc.nextInt() - 1][sc.nextInt() - 1] = 1;

        k = sc.nextInt();
        for (int i = 0; i < k; i++)
            chessBoard[sc.nextInt() - 1][sc.nextInt() - 1] = 2;

        k = sc.nextInt();
        for (int i = 0; i < k; i++)
            chessBoard[sc.nextInt() - 1][sc.nextInt() - 1] = 3;

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (chessBoard[i][j] == 1)
                    Queen(j, i);
                else if (chessBoard[i][j] == 2)
                    Knight(j, i);
            }
        }

        for (int i = 0; i < N; i++)
            for (int j = 0; j < M; j++)
                if (chessBoard[i][j] == 0) //체스판이 0이면 Knight나 Queen의 이동 경로에 없다.
                    count++;

        System.out.println(count);
    }
    public static void Knight(int x, int y) {
        for (int i = 0; i < 8; i++) {
            int knightX = x + Knight_X[i];
            int knightY = y + Knight_Y[i];

            if (knightX >= 0 && knightX < M && knightY < N && knightY >= 0)
                if (chessBoard[knightY][knightX] == 0) //Knight 이동 경로 체크
                    chessBoard[knightY][knightX] = -1;
        }
    }
    public static void Queen(int x, int y) {
        for (int i = 0; i < 8; i++) {
            int queenX = x + Queen_X[i];
            int queenY = y + Queen_Y[i];

            while (queenX >= 0 && queenX < M && queenY < N && queenY >= 0 && chessBoard[queenY][queenX] <= 0) {
                chessBoard[queenY][queenX] = -1; //Queen 이동 경로 체크
                queenX += Queen_X[i];
                queenY += Queen_Y[i];
            }
        }
    }
}

2019-03-22 [JAVA]백준 1890번 - 점프

|

문제 출처

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

문제 접근(실패)

  • Queue를 이용하기
  • 0,0 부터 시작하여 점프가능한 곳을 큐에 넣고 도착 지점 개수 세기
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class Baekjoon_1890 {
    static int n;
    static Jump[][] map;
    static int count = 0;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        n = sc.nextInt();
        map = new Jump[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                map[i][j] = new Jump(j, i, sc.nextInt());
            }
        }

        dp(0, 0);
        System.out.println(count);
    }

    public static void dp(int x, int y) {
        Queue<Jump> q = new LinkedList<>();
        q.offer(map[y][x]);

        while (!q.isEmpty()) {
            Jump tmp = q.poll();

            if (tmp.y == n-1 && tmp.x == n-1) {
                count++;
                continue;
            }

            if (tmp.value + tmp.y < n) {
                q.offer(map[tmp.value + tmp.y][tmp.x]);
            }
            if (tmp.value + tmp.x < n) {
                q.offer(map[tmp.y][tmp.value + tmp.x]);
            }

        }
    }
}
class Jump {
    int x, y;
    int value;

    Jump(int x, int y, int value) {
        this.x = x;
        this.y = y;
        this.value = value;
    }
}

=> 메모리, 시간 초과

문제 접근

  • 다이나믹 프로그래밍

  • 행 마다 가로로 갈 수 있는 경우 체크 -> 열마다 세로로 갈 수 있는 경우 체크
  • 반복
import java.util.Scanner;

public class Baekjoon_1890 {
    static int[][] map;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        map = new int[n][n];
        long[][] dp = new long[n][n];

        for (int i=0; i<n; i++)
            for (int j=0; j<n; j++)
                map[i][j] = sc.nextInt();

        dp[0][0] = 1;
        for (int i=0; i<n; i++){
            for (int j=0; j<n; j++){
              //행 마다 가로로 갈 수 있는 경우 체ㅋㅡ
                if(dp[i][j] != 0 ){
                    if(map[i][j]+j<n){
                        if(j == n-1)
                            break;
                        if(map[i][j]!= 0)
                            dp[i][map[i][j]+j] +=dp[i][j];
                        else
                            dp[i][j] = 0;
                    }
                }
            }
					//열마다 세로로 갈 수 있는 경우 체크
            for (int j=0; j<n; j++){
                if(dp[i][j] != 0){
                    if(map[i][j]+i<n){
                        if(i == n-1)
                            break;
                        if(map[i][j]!= 0)
                            dp[map[i][j]+i][j] +=dp[i][j];
                        else
                            dp[i][j] = 0;
                    }
                }
            }
        }
        System.out.println(dp[n-1][n-1]);
    }
}

2019-03-28 [JAVA]백준 14499번 - 주사위 굴리기

|

문제 출처

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

문제

주사위 굴리기

시간 제한 메모리 제한 제출 정답 맞은 사람 정답 비율
2 초 512 MB 10544 4038 2962 39.689%

문제

크기가 N×M인 지도가 존재한다. 지도의 오른쪽은 동쪽, 위쪽은 북쪽이다. 이 지도의 위에 주사위가 하나 놓여져 있으며, 주사위의 전개도는 아래와 같다. 지도의 좌표는 (r, c)로 나타내며, r는 북쪽으로부터 떨어진 칸의 개수, c는 서쪽으로부터 떨어진 칸의 개수이다.

  2
4 1 3
  5
  6

주사위는 지도 위에 윗 면이 1이고, 동쪽을 바라보는 방향이 3인 상태로 놓여져 있으며, 놓여져 있는 곳의 좌표는 (x, y) 이다. 가장 처음에 주사위에는 모든 면에 0이 적혀져 있다.

지도의 각 칸에는 정수가 하나씩 쓰여져 있다. 주사위를 굴렸을 때, 이동한 칸에 쓰여 있는 수가 0이면, 주사위의 바닥면에 쓰여 있는 수가 칸에 복사된다. 0이 아닌 경우에는 칸에 쓰여 있는 수가 주사위의 바닥면으로 복사되며, 칸에 쓰여 있는 수는 0이 된다.

주사위를 놓은 곳의 좌표와 이동시키는 명령이 주어졌을 때, 주사위가 이동했을 때 마다 상단에 쓰여 있는 값을 구하는 프로그램을 작성하시오.

주사위는 지도의 바깥으로 이동시킬 수 없다. 만약 바깥으로 이동시키려고 하는 경우에는 해당 명령을 무시해야 하며, 출력도 하면 안된다.

입력

첫째 줄에 지도의 세로 크기 N, 가로 크기 M (1 ≤ N, M ≤ 20), 주사위를 놓은 곳의 좌표 x y(0 ≤ x ≤ N-1, 0 ≤ y ≤ M-1), 그리고 명령의 개수 K (1 ≤ K ≤ 1,000)가 주어진다.

둘째 줄부터 N개의 줄에 지도에 쓰여 있는 수가 북쪽부터 남쪽으로, 각 줄은 서쪽부터 동쪽 순서대로 주어진다. 주사위를 놓은 칸에 쓰여 있는 수는 항상 0이다. 지도의 각 칸에 쓰여 있는 수는 10을 넘지 않는 자연수이다.

마지막 줄에는 이동하는 명령이 순서대로 주어진다. 동쪽은 1, 서쪽은 2, 북쪽은 3, 남쪽은 4로 주어진다.

출력

이동할 때마다 주사위의 윗 면에 쓰여 있는 수를 출력한다. 만약 바깥으로 이동시키려고 하는 경우에는 해당 명령을 무시해야 하며, 출력도 하면 안된다.

문제 풀이

  1. 바닥을 기준으로
  • 바닥 - 북 - 위 - 남 (세로)
  • 바닥 - 동 - 위 - 서 (가로)

2가지 경우를 나누에 생각함.

    static int[] horizonDice = new int[4];
    static int[] verticalDice = new int[4];
  1. 기본적인 조건을 생각한다.
  • 이동한 칸에 쓰여 있는 수가 0이면, 주사위의 바닥면에 쓰여 있는 수가 칸에 복사된다.

  • 0이 아닌경우에는 칸에 쓰여 있는 수가 주사위의 바닥면으로 복사되며, 칸에 쓰여 있는 수는 0이 된다.

if(map[locationY][locationX] ==0){
            //이동한 칸에 쓰여 있는 수가 0이면, 주사위의 바닥면에 쓰여 있는 수가 칸에 복사된다.
            map[locationY][locationX] = horizonDice[0];
        }else{
            //0이 아닌 경우에는 칸에 쓰여 있는 수가 주사위의 바닥면으로 복사되며, 칸에 쓰여 있는 수는 0이 된다.
            horizonDice[0] = verticalDice[0] = map[locationY][locationX];
            map[locationY][locationX] =0;
        }
  1. 주사위를 굴린다.

북쪽으로 굴린다고 가정하면 세로축이 한칸씩 밀린다.

  • 바닥 -> 남
  • 북 -> 바닥
  • 위 -> 북
  • 남 -> 위
if (locationY - 1 >=0) { //지도 범위 내일 때
                locationY--;
                int tmp = verticalDice[0];
                for (int i = 0; i<3; i++)
                    verticalDice[i] = verticalDice[i+1];
                verticalDice[3] = tmp;

                horizonDice[0] = verticalDice[0];
                horizonDice[2]= verticalDice[2];
}

전체 소스

import java.util.Scanner;

public class Baekjoon_14499 {
    static int N, M;
    static int[][] map;
    static int locationX, locationY;
    static int[] horizonDice = new int[4];
    static int[] verticalDice = new int[4];
    //주사위 vertical 0: 바닥 1:북 2:위 3:남 horizontal 0: 바닥 1: 동 2: 위 3: 서. 초기 바닥 6, 위 1, 동 3 서 4 남 5 북 2
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        N = sc.nextInt();
        M = sc.nextInt();

        locationY = sc.nextInt(); //현재 위치
        locationX = sc.nextInt();
        map = new int[N][M];

        int k = sc.nextInt(); //횟수

        for (int i=0; i<N; i++){
            for (int j=0; j<M; j++){
                map[i][j] = sc.nextInt();
            }
        }

        map[locationY][locationX] =0; //주사위를 놓은 칸에 쓰여 있는 수는 항상 0

        Print();
        for (int i=0; i<k ;i++)
            moveDice(sc.nextInt());

    }
    static void Print(){
        if(map[locationY][locationX] ==0){
            //이동한 칸에 쓰여 있는 수가 0이면, 주사위의 바닥면에 쓰여 있는 수가 칸에 복사된다.
            map[locationY][locationX] = horizonDice[0];
        }else{
            //0이 아닌 경우에는 칸에 쓰여 있는 수가 주사위의 바닥면으로 복사되며, 칸에 쓰여 있는 수는 0이 된다.
            horizonDice[0] = verticalDice[0] = map[locationY][locationX];
            map[locationY][locationX] =0;
        }
    }
    public static void moveDice(int a){ //주사위 이동
        if(a == 1){ //동
            if(locationX+1<M){
                locationX++;
                int tmp = horizonDice[0];

                horizonDice[0] = tmp; //큐 활용
                for (int i = 0; i<3; i++)
                    horiznDice[i] = horizonDice[i+1];
                horizonDice[3] = tmp;

                verticalDice[0] = horizonDice[0];
                verticalDice[2]= horizonDice[2];
                Print();
                System.out.println(horizonDice[2]);
            }
        }else if(a == 2){ //서
            if(locationX-1>=0){
                locationX--;
                int tmp = horizonDice[3];
                for (int i=3; i>0; i--)
                    horizonDice[i] = horizonDice[i-1];

                horizonDice[0] = tmp;

                verticalDice[0] = horizonDice[0];
                verticalDice[2]= horizonDice[2];
                Print();
                System.out.println(horizonDice[2]);
            }

        }else if( a== 3){ //북
            if (locationY - 1 >=0) {
                locationY--;
                int tmp = verticalDice[0];
                for (int i = 0; i<3; i++)
                    verticalDice[i] = verticalDice[i+1];
                verticalDice[3] = tmp;

                horizonDice[0] = verticalDice[0];
                horizonDice[2]= verticalDice[2];
                Print();
                System.out.println(horizonDice[2]);
            }

        }else if( a== 4){ //남
            if(locationY+1<N){
                locationY++;
                int tmp = verticalDice[3];
                for (int i=3; i>0; i--)
                    verticalDice[i] = verticalDice[i-1];
                verticalDice[0] = tmp;

                horizonDice[0] = verticalDice[0];
                horizonDice[2]= verticalDice[2];
                Print();
                System.out.println(horizonDice[2]);
            }
        }

    }
}