BOJ_14999_주사위굴리기_JAVA
문제 : 주사위굴리기
링크 : BOJ_14999_주사위굴리기
접근 방식
감을 잡기가 너무 어려운 문제였다. 문제를 이해하기 위해 집에 있는 주사위를 찾아서 굴려보기도 했다.
전개도와 초기 방향이 정해져있는 주사위를 2차원 배열 판에서 굴리면서 배열 판의 바닥이 0이면 주사위의 숫자를 덮어씌우고, 바닥이 0이 아니라면 바닥의 숫자를 주사위에 덮어씌워야 하는 문제이다.
먼저 숫자로 되어있는 전개도를 제대로 인식할 필요가 있다. 주사위의 전개도에 보이는 숫자(key)와, 주사위에 적히는 숫자(value)를 제대로 구분지어 인식해야 헷갈리지 않는다.
두 번째로, 주사위가 굴러갈 때 어떻게 주사위의 각 면이 어떻게 굴러가는지 살펴봐야한다. 동서남북, 각각의 방향에 따라서 위쪽을 기준으로 전개도의 어떤 숫자(key)가 어느 위치에 있는지 확인할 필요가 있다.
소스 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
public class BOJ_14999_주사위굴리기 {
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(in.readLine(), " ");
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
int X = Integer.parseInt(st.nextToken());
int Y = Integer.parseInt(st.nextToken());
int K = Integer.parseInt(st.nextToken());
int arr[][] = new int[N][M];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(in.readLine(), " ");
for (int j = 0; j < M; j++) {
arr[i][j] = Integer.parseInt(st.nextToken());
}
}
// 윗면 1, 아랫면 6, 오른쪽 3, 왼쪽 4, 위쪽 2, 아래쪽 5
st = new StringTokenizer(in.readLine(), " ");
Map<Integer, Integer> dice = new HashMap<>();
for (int i = 1; i <= 6; i++) {
dice.put(i, 0);
}
int[][] dir = { { 0, 0 }, { 0, 1 }, { 0, -1 }, { -1, 0 }, { 1, 0 } };
// 위 기준으로 동, 서, 남, 북
int top = 1;
int base = 6;
int east = 3;
int west = 4;
int north = 5;
int south = 2;
for (int i = 0; i < K; i++) {
int C = Integer.parseInt(st.nextToken());
int dx = X + dir[C][0];
int dy = Y + dir[C][1];
if (dx < 0 || dx >= N || dy < 0 || dy >= M) {
continue;
}
int temp = 0;
switch (C) {
// 동쪽으로 굴렀을 때
case 1:
// 천장 임시저장
temp = top;
// 서 -> 천장
top = west;
// 바닥 -> 서
west = base;
// 동 -> 바닥
base = east;
// 천장 -> 동
east = temp;
break;
// 서쪽으로 굴렀을 때
case 2:
temp = top;
top = east;
east = base;
base = west;
west = temp;
break;
// 북쪽으로 굴렀을 때
case 3:
temp = top;
top = south;
south = base;
base = north;
north = temp;
break;
// 남쪽으로 굴렀을 때
case 4:
temp = top;
top = north;
north = base;
base = south;
south = temp;
break;
}
// System.out.printf("%d %d %d %d %d %d\n", top, east, base, west, north, south);
System.out.println(dice.get(top));
if (arr[dx][dy] != 0) {
dice.replace(base, arr[dx][dy]);
arr[dx][dy] = 0;
}else {
arr[dx][dy] = dice.get(base);
}
X = dx;
Y = dy;
}
}
}
풀이 방법
-
line 13 ~ 30 : 값을 입력받고 2차원 배열 판을 완성하는 부분이다. x,y좌표로 입력받는다고 해서 y좌표가 행을 의미하는 것은 아니다.
-
line 32 : 사방탐색을 할 2차원 방향 배열이다. 1,2,3,4 순서대로 동서북남이기 때문에, 배열의 값을 1부터 순차적으로 집어넣어주었다.
-
line 33 : 전개도의 숫자를 Key로 값을 저장하도록 Map을 생성하였다.
-
line 35 ~ 37 : Map의 각 면을 0으로 초기화해준다.(1면부터 6면까지)
-
line 42 : 명령어 목록을 읽어온다.
-
line 45 ~ 50 : 주사위의 초기 방향을 설정한다.(윗면이 1, 동쪽이 3)
-
line 52 ~ 102 : 주사위를 굴리는 부분이다. 명령어의 위치대로 주사위의 임시 위치를 설정한다. 만약 주사위가 배열의 범위를 벗어나려고하면 바로 반복문을 continue 시킨다. 주사위를 굴리는데, 위에서 설정한 초기 방향에서 주사위를 굴리는 방향에 따라 각 주사위 면을 다시 세팅해주도록 한다.
-
line 104 ~ 112 : 주사위의 윗면을 출력하고, 바닥이 0인지 아닌지 여부에 따라 주사위에 값을 덮어씌우거나, 바닥에 값을 덮어씌우거나 둘 중에 하나의 로직을 수행한다. 그 후, 주사위 좌표를 이동한 위치로 옮겨준다.
언뜻 보기에 문제파악이 대단히 어려운 문제였다. 실제로 이런 문제가 코딩테스트로 나온다고 할 때는 주사위를 구할 수 없을테니 머릿속으로 도형이나 공간에 대한 부분을 생각할 수 있게끔 사고하는 연습이 필요할 듯 하다.