문제
크기가 N×M인 지도가 존재한다. 지도의 오른쪽은 동쪽, 위쪽은 북쪽이다. 이 지도의 위에 주사위가 하나 놓여져 있으며, 주사위의 전개도는 아래와 같다. 지도의 좌표는 (r, c)로 나타내며, r는 북쪽으로부터 떨어진 칸의 개수, c는 서쪽으로부터 떨어진 칸의 개수이다.
2 4 1 3 5 6
주사위는 지도 위에 윗 면이 1이고, 동쪽을 바라보는 방향이 3인 상태로 놓여져 있으며, 놓여져 있는 곳의 좌표는 (x, y) 이다. 가장 처음에 주사위에는 모든 면에 0이 적혀져 있다.
지도의 각 칸에는 정수가 하나씩 쓰여져 있다. 주사위를 굴렸을 때, 이동한 칸에 쓰여 있는 수가 0이면, 주사위의 바닥면에 쓰여 있는 수가 칸에 복사된다. 0이 아닌 경우에는 칸에 쓰여 있는 수가 주사위의 바닥면으로 복사되며, 칸에 쓰여 있는 수는 0이 된다.
주사위를 놓은 곳의 좌표와 이동시키는 명령이 주어졌을 때, 주사위가 이동했을 때 마다 상단에 쓰여 있는 값을 구하는 프로그램을 작성하시오.
주사위는 지도의 바깥으로 이동시킬 수 없다. 만약 바깥으로 이동시키려고 하는 경우에는 해당 명령을 무시해야 하며, 출력도 하면 안 된다.
풀이
주사위 모양을 2차원 배열로 생각해서 풀면 쉽다.
위 아래 회전은 쉽게 생각할 수 있을 것이다.
위의 경우는 가운데 열을 하나씩 위로 올리면 된다.
아래의 경우는 가운데 열을 하나씩 아래로 내리면 된다.
오른쪽 왼쪽 회전이 좀 복잡하지만 오른쪽의 경우로 그림을 그려 표현하면
위 그림과 같이 숫자를 이동시키면 된다.
왼쪽의 경우는 화살표 방향만 반대로 숫자를 이동시킨다고 생각하면 편하다.
이렇게 이동시킨 배열의 dice[1][1] 가 위방향 dice[3][1] 이 바닥 방향이다
dice[1][1] 부분을 저장하고
dice[3][1] 부분의 수로 map 을 바꾸거나 map의 숫자를 저장하면 된다.
<전체코드>
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int N, M, K;
static int[][] map;
static Dice dice;
static int[][] move = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
static StringBuilder sb = new StringBuilder();
public static int parseInt(String string) {
return Integer.parseInt(string);
}
public static void main(String[] args) throws IOException{
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(bufferedReader.readLine());
N = parseInt(st.nextToken());
M = parseInt(st.nextToken());
int x = parseInt(st.nextToken());
int y = parseInt(st.nextToken());
K = parseInt(st.nextToken());
dice = new Dice(x, y);
map = new int[N][M];
for(int i = 0 ; i < N ; i++) {
st = new StringTokenizer(bufferedReader.readLine());
for(int j = 0 ; j < M ; j++) {
map[i][j] = parseInt(st.nextToken());
}
}
st = new StringTokenizer(bufferedReader.readLine());
for(int i = 0 ; i < K ; i++) {
int order = parseInt(st.nextToken()) - 1;
int nx = dice.x + move[order][0];
int ny = dice.y + move[order][1];
if(nx < 0 || nx >= N || ny < 0 || ny >= M) { continue;}
switch(order) {
case 0:
moveRight(dice);
break;
case 1:
moveLeft(dice);
break;
case 2:
moveUp(dice);
break;
case 3:
moveDown(dice);
break;
}
dice.x = nx;
dice.y = ny;
if(map[dice.x][dice.y] == 0) {
map[dice.x][dice.y] = dice.number[3][1];
}
else {
dice.number[3][1] = map[dice.x][dice.y];
map[dice.x][dice.y] = 0;
}
sb.append(dice.number[1][1]).append("\n");
}
System.out.print(sb);
}
static void moveLeft(Dice dice) {
int[][] number = dice.number;
int tmp = number[1][0];
for(int i = 0 ; i < 2 ; i++) {
number[1][i] = number[1][i + 1];
}
number[1][2] = number[3][1];
number[3][1] = tmp;
}
static void moveRight(Dice dice) {
int[][] number = dice.number;
int tmp = number[1][2];
for(int i = 2 ; i > 0 ; i--) {
number[1][i] = number[1][i - 1];
}
number[1][0] = number[3][1];
number[3][1] = tmp;
}
static void moveDown(Dice dice) {
int[][] number = dice.number;
int tmp = number[3][1];
for(int i = 3 ; i > 0 ; i--) {
number[i][1] = number[i - 1][1];
}
number[0][1] = tmp;
}
static void moveUp(Dice dice) {
int[][] number = dice.number;
int tmp = number[0][1];
for(int i = 0 ; i < 3 ; i++) {
number[i][1] = number[i + 1][1];
}
number[3][1] = tmp;
}
static class Dice{
int[][] number;
int x, y;
public Dice(int x, int y) {
this.x = x;
this.y = y;
this.number = new int[4][3];
}
}
}
'알고리즘 공부 > 구현 , 시뮬레이션' 카테고리의 다른 글
[백준] 20061 모노미도미노 2 (0) | 2021.10.20 |
---|---|
[백준] 14503 로봇 청소기 (0) | 2021.10.20 |
[백준] 16234 인구 이동 (0) | 2021.10.19 |
[백준] 19238 스타트 택시 (0) | 2021.10.19 |
[백준] 15686 치킨배달 (0) | 2021.10.19 |