알고리즘/백준
백준 14499번 (JAVA) 주사위굴리기
왕구스
2021. 4. 21. 17:38
시뮬레이션의 조건은 이러하다.
1. 주사위는 이동할때 굴려진다(오른쪽으로 이동한다고 가정하면, 오른쪽 면이 바닥으로 오고, 기존에 위를 보고있던 면이 오른쪽으로 오며, 바닥면이 왼쪽으로 온다는 의미)
2. 굴린 이후 이동한 자리의 숫자가 0이 아니라면 주사위 바닥면의 숫자가 칸의 숫자로 바뀌게되고, 칸에 쓰여진 숫자는 0이 된다(이 조건을 못보고 넘어가서 디버깅에 시간이 걸렸다)
3. 이동할때마다 위를 보고있는 면의 번호를 출력한다.
4. 지도 외곽으로 나가는 명령은 출력하지않는다.
나는 이 문제를 Node클래스 내부에 두개의 LinkedList를 만들어서 관리하는 것으로 해결했다.
1. (위, 오른쪽, 바닥, 왼쪽)의 번호가 순서대로 저장되는 hNums
2. (위, 아랫면, 바닥, 윗면)의 번호가 순서대로 저장되는 vNums
static class Node {
int x;
int y;
LinkedList<Integer> vNums; // top down bot up
LinkedList<Integer> hNums; // top right bot left
Node(int x, int y) {
this.x = x;
this.y = y;
hNums = new LinkedList<Integer>();
vNums = new LinkedList<Integer>();
for (int i = 0; i < 4; i++) {
hNums.add(0);
vNums.add(0);
}
}
}
이후 dir에 따라 움직일때마다
switch (m) {
case 1: // 동 (왼쪽면에 있던걸 탑으로)
cube.hNums.addFirst(cube.hNums.pollLast());
sysnc(0);
break;
case 2: // 서
cube.hNums.addLast(cube.hNums.pollFirst());
sysnc(0);
break;
case 3: // 북
cube.vNums.addLast(cube.vNums.pollFirst());
sysnc(1);
break;
case 4: // 남
cube.vNums.addFirst(cube.vNums.pollLast());
sysnc(1);
break;
}
이러한 형태로 넘기면서 해결했다. 다만, top 과 bot은 두 list 모두에 존재하므로, 한쪽이 변경되면 다른 한쪽도 변경하도록하였다.
private static void sysnc(int type) {
if (type == 0) {
cube.vNums.remove(0);
cube.vNums.add(0, cube.hNums.get(0));
cube.vNums.remove(2);
cube.vNums.add(2, cube.hNums.get(2));
} else {
cube.hNums.remove(0);
cube.hNums.add(0, cube.vNums.get(0));
cube.hNums.remove(2);
cube.hNums.add(2, cube.vNums.get(2));
}
}
아래는 코드 전문이다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class BOJ_14499_주사위굴리기 {
static int N, M, K, map[][];
static Node cube;
static Queue<Integer> order = new ArrayDeque<>();
static int[] dx = { 0, 0, -1, 1 };// 오른쪽, 왼쪽, 위쪽, 아래쪽(동서북남)
static int[] dy = { 1, -1, 0, 0 };// 오른쪽, 왼쪽, 위쪽, 아래쪽(동서북남)
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = stoi(st.nextToken());
M = stoi(st.nextToken());
map = new int[N][M];
cube = new Node(stoi(st.nextToken()), stoi(st.nextToken()));
K = stoi(st.nextToken()); // 안쓰는데 혹시몰라서 받아둠
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < M; j++) {
map[i][j] = stoi(st.nextToken());
}
}
st = new StringTokenizer(br.readLine());
while (st.hasMoreTokens()) {
order.add(stoi(st.nextToken()));
}
move();
}
private static void move() {
while (!order.isEmpty()) {
int m = order.poll();
int nx = cube.x + dx[m - 1];
int ny = cube.y + dy[m - 1];
if (!isValid(nx, ny)) {
continue;
}
cube.x = nx;
cube.y = ny;
// 주사위 방향 돌린 후 큐브 바닥면과 지도 숫자 확인해서 복사하고 상단숫자 출력
switch (m) {
case 1: // 동 (왼쪽면에 있던걸 탑으로)
cube.hNums.addFirst(cube.hNums.pollLast());
sysnc(0);
break;
case 2: // 서
cube.hNums.addLast(cube.hNums.pollFirst());
sysnc(0);
break;
case 3: // 북
cube.vNums.addLast(cube.vNums.pollFirst());
sysnc(1);
break;
case 4: // 남
cube.vNums.addFirst(cube.vNums.pollLast());
sysnc(1);
break;
}
if (map[nx][ny] == 0) { // 주사위 바닥면을 map에 복사
map[nx][ny] = cube.vNums.get(2);
} else { // 바닥숫자를 주사위 바닥면에 복사
botCopy(map[nx][ny]);
map[nx][ny] = 0;
}
System.out.println(cube.vNums.get(0));
}
}
private static void botCopy(int num) {
cube.vNums.remove(2);
cube.hNums.remove(2);
cube.vNums.add(2, num);
cube.hNums.add(2, num);
}
private static void sysnc(int type) {
if (type == 0) {
cube.vNums.remove(0);
cube.vNums.add(0, cube.hNums.get(0));
cube.vNums.remove(2);
cube.vNums.add(2, cube.hNums.get(2));
} else {
cube.hNums.remove(0);
cube.hNums.add(0, cube.vNums.get(0));
cube.hNums.remove(2);
cube.hNums.add(2, cube.vNums.get(2));
}
}
private static boolean isValid(int nx, int ny) {
return 0 <= nx && 0 <= ny && nx < N && ny < M;
}
static class Node {
int x;
int y;
LinkedList<Integer> vNums; // top down bot up
LinkedList<Integer> hNums; // top right bot left
Node(int x, int y) {
this.x = x;
this.y = y;
hNums = new LinkedList<Integer>();
vNums = new LinkedList<Integer>();
for (int i = 0; i < 4; i++) {
hNums.add(0);
vNums.add(0);
}
}
}
public static int stoi(String s) {
return Integer.parseInt(s);
}
}