https://www.acmicpc.net/problem/14499
문제 개요
이 문제는 크기가 N×M인 지도 위에서 주사위를 굴리며 주어진 명령에 따라 이동시키고, 이동한 후의 주사위 상태를 업데이트하는 시뮬레이션 문제입니다.
주사위의 전개도는 주어진 상태를 기반으로 동쪽, 서쪽, 북쪽, 남쪽으로 굴릴 때 각 면의 값을 적절히 변경해야 하며, 주사위가 지도 위를 이동할 때 다음 규칙을 따릅니다:
- 이동한 칸에 쓰여 있는 값이 0이면 주사위의 바닥면 값을 그 칸에 복사합니다.
- 이동한 칸에 값이 0이 아니면, 해당 값을 주사위의 바닥면에 복사하고, 칸의 값은 0으로 변경됩니다.
- 주사위가 지도 밖으로 벗어나는 이동 명령은 무시합니다.
접근 방법
1. 주사위 전개도의 표현
주사위의 전개도를 배열로 표현하여 굴릴 때 각 면의 값을 갱신하는 방식을 사용했습니다.
주사위의 전개도는 아래와 같이 4×3 배열로 나타냅니다
- dice[1][1]은 항상 주사위의 윗면을 나타냅니다.
- dice[3][1]은 항상 주사위의 바닥면을 나타냅니다
2. 이동 명령 구현
명령에 따라 주사위를 굴리는 함수 east(), west(), north(), south()를 정의했습니다. 각 함수는 아래 단계를 거칩니다:
- 지도 범위 체크: 명령에 따른 이동이 지도의 범위를 벗어난 경우 무시.
- 주사위 상태 갱신: 명령 방향에 따라 주사위 전개도의 값을 갱신.
- 지도 값 처리: 이동한 칸의 값에 따라 주사위와 지도의 값을 교환하거나 복사.
- 주사위 상단 출력: 갱신 후 dice[1][1] 값을 출력.
3. 주사위 굴리기
- 동쪽(east())과 서쪽(west()): 주사위 전개도의 가로축 값들을 회전시킵니다.
- 북쪽(north())과 남쪽(south()): 전개도의 세로축 값을 회전시킵니다.
예를 들어, 동쪽으로 굴릴 때:
- [1][1](윗면)은 [1][0](왼쪽)으로, [1][0]은 [3][1](바닥)으로, [3][1]은 [1][2](오른쪽)으로 이동합니다.
4. 지도 값 처리
이동한 칸의 값이 0인지 아닌지에 따라 주사위와 지도의 값을 교환하거나 복사합니다:
- map[r][c] == 0: 주사위 바닥면 값을 map[r][c]에 복사.
- map[r][c] != 0: map[r][c] 값을 주사위 바닥면에 복사 후, 칸의 값은 0으로 초기화.
5. 전체 시뮬레이션
모든 명령어를 반복하며 위 과정을 수행합니다:
- 주어진 명령어 순서를 차례로 읽어 명령에 따라 주사위를 굴립니다.
- 각 이동 후 주사위의 윗면 값을 출력합니다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int[][] dice = new int[4][3];
static int[][] map;
static int N, M, r, c, cntCmd;
static int[] cmd;
public static void main(String[] args) throws IOException {
init();
for(int i=0; i<cmd.length; i++) {
switch (cmd[i]) {
case 1:
east();
break;
case 2:
west();
break;
case 3:
north();
break;
case 4:
south();
break;
}
}
}
public static void check() {
if(map[r][c] == 0) {
map[r][c] = dice[3][1];
} else {
dice[3][1] = map[r][c];
map[r][c] = 0;
}
}
public static void east() {
if(r<0 || c+1<0 || r>=map.length || c+1>=map[0].length) return;
int tmp = dice[1][1];
dice[1][1] = dice[1][0];
dice[1][0] = dice[3][1];
dice[3][1] = dice[1][2];
dice[1][2] = tmp;
c+=1;
check();
System.out.println(dice[1][1]);
}
public static void west() {
if(r<0 || c-1<0 || r>=map.length || c-1>=map[0].length) return;
int tmp = dice[1][1];
dice[1][1] = dice[1][2];
dice[1][2] = dice[3][1];
dice[3][1] = dice[1][0];
dice[1][0] = tmp;
c-=1;
check();
System.out.println(dice[1][1]);
}
public static void north() {
if(r-1<0 || c<0 || r-1>=map.length || c>=map[0].length) return;
int tmp = dice[1][1];
dice[1][1] = dice[2][1];
dice[2][1] = dice[3][1];
dice[3][1] = dice[0][1];
dice[0][1] = tmp;
r-=1;
check();
System.out.println(dice[1][1]);
}
public static void south() {
if(r+1<0 || c<0 || r+1>=map.length || c>=map[0].length) return;
int tmp = dice[1][1];
dice[1][1] = dice[0][1];
dice[0][1] = dice[3][1];
dice[3][1] = dice[2][1];
dice[2][1] = tmp;
r+=1;
check();
System.out.println(dice[1][1]);
}
public static void init() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
r = Integer.parseInt(st.nextToken());
c = Integer.parseInt(st.nextToken());
cntCmd = Integer.parseInt(st.nextToken());
map = new int[N][M];
cmd = new int[cntCmd];
for(int i=0; i<N; i++) {
st = new StringTokenizer(br.readLine());
for(int j=0; j<M; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
}
st = new StringTokenizer(br.readLine());
for(int i=0; i<cntCmd; i++) {
cmd[i] = Integer.parseInt(st.nextToken());
}
}
}
'문제 > 백준' 카테고리의 다른 글
[백준] 14890 경사로 - Java (1) | 2025.01.24 |
---|---|
[백준] 14503 로봇 청소기 - Java (1) | 2025.01.19 |
[백준] 10799 쇠막대기 - Java (0) | 2024.10.31 |
[백준] 4920 테트리스 게임 - Java (0) | 2024.10.30 |
[백준] 1654 랜선 자르기 - Java (2) | 2024.10.25 |