문제 탐색하기
입력 자료 정리
- n은 지도의 세로 크기, m은 지도의 가로 크기다.
- x는 주사위를 처음 놓는 y좌표, y는 주사위를 처음 놓는 x좌표다
- 그리고 이어서 오는 k는 명령의 개수다
- 이후 들어오는 n x m개의 값은 각 좌표의 바닥면 값이다
- 마지막으로 들어오는 k개의 입력값은 주사위의 이동방향에 대한 값이다
1은 동쪽, 2는 서쪽, 3은 북쪽, 4는 남쪽을 의미한다
해결방법 추론
- 입력값도 작고, 주어진 문제 형태를 보면 조건에 맞춰서 구현하는 문제다
- 각 명령어마다 3가지 조건에 맞춰서 설계하면 정답을 구할 수 있을 것이다!
- 또한 이 문제는 주사위가 이동할 때마다 조건에 맞춰서 변화하기 때문에,
현재 위치와 주사위 면의 상태를 관리해야한다.
해당 문제는 별도의 클래스를 설계한다음 인스턴스로 관리하면 될 것이다
- 3가지 조건은 순서에 맞게 설계해야한다. 먼저 주사위가 이동하는 것이 첫번쨰 순서이며,
주사위면의 회전이 두번째고 바닥면과 주사위 바닥면을 비교하여 값을 변경하는 것이 세번째다
- 이 순서에 맞춰서 설계한다면 정답을 구할 수 있을 것이다!
시간복잡도 계산
- 시간복잡도는 k의 입력값이 가장 크기 때문에 k의 연산만 고려한다
- 따라서 시간복잡도는 O(k)가 되고, k의 최대 입력값은 1000이므로 시간제한 안에 문제를 해결할 수 있다
코드 설계하기
입력값 상태 관리
- 각 입력값들은 int형 변수에 관리한다
- nxm크기의 2차원 int형 배열을 선언해서 지도의 각 값을 관리한다
- k만큼 들어오는 순서는 int형 변수로 받는다.
- 설계한 구현 코드의 결과를 int형 변수 a로 받는다. 이 값에 따라서 출력할지 여부를 결정할 것이다
만약 1이면 출력하고 0이면 출력하지 않는다
주사위 상태관리
- 주사위의 상태를 관리할 Dice 클래스를 별도로 구현했다
- 각 필드는 주사위의 현재 y좌표, x좌표, 그리고 6개의 면에 들어간 숫자를 의미한다
구현 코드 설계
- 아래 로직을 모두 통과하면 1을 리턴한다
이동 로직 설계
- 이동 로직은 4가지 방향에 따라 다르게 이동해야한다. 1은 동쪽, 2는 서쪽, 3은 북쪽, 4는 남쪽이다
- 동쪽은 x를 늘리고, 서쪽은 x를 줄인다. 북쪽은 y를 줄이고, 남쪽은 y를 늘린다
- 줄일때는 그 값이 0이상인지 확인하고 늘릴때는 n이나 m 미만인지 확인한다.
범위안에 포함되는 경우만 주사위의 현재 좌표를 증감한다.
- 만약 범위안에 포함되지 않는 경우 바로 0을 리턴한다
주사위면 변경 로직 설계
- 이어서 이동방향에 따라 주사위면의 값을 회전시키는 로직이다
- 동쪽으로 이동할 경우, 1,4번 면은 고정되고 나머지 면은 다음과 같이 변동한다
3 -> 0 -> 2 -> 5 -> 3
- 주사위 인스턴스의 값만으로 구현하면, 이전에 덮힌 값으로 변경되기 때문에 별도의 배열을 클론해서 활용한다
- 서쪽으로 이동할 경우, 똑같이 1,4번 면은 고정되고 나머지 면은 다음과 같이 변동한다
2 -> 0 -> 3 -> 5 -> 2
- 북쪽으로 이동할 경우, 2,3번 면은 고정되고 나머지 면은 다음과 같이 변동한다
4 -> 0 -> 1 -> 5 -> 4
- 남쪽으로 이동할 경우 똑같이 2,3번 면은 고정되고 나머지 면은 다음과 같이 변동한다
1 -> 0 -> 4 -> 5 -> 1
주사위면 or 바닥면 변경로직 설계
- 이번에는 지도의 바닥면의 값에 따라 주사위의 바닥면이나 지도의 바닥면이 변경되는 로직이다
- 지도의 바닥면이 0이면, 주사위의 바닥면인 5번 면을 지도 바닥면에 넣는다
- 만약 아닐 경우, 주사위의 바닥면에 지도의 바닥면을 넣고 지도의 바닥면은 0으로 초기화한다
출력값 설계
- 위 구현값의 리턴 결과가 1인 경우, 주사위의 위쪽면인 0번면을 출력하면 정답이 된다.
정답 코드
import java.io.*;
import java.util.*;
class Dice{
int nowY;
int nowX;
int[] diceNum;
Dice(int nowY, int nowX){
this.nowY = nowY;
this.nowX = nowX;
diceNum = new int[6];
}
}
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
int startY = Integer.parseInt(st.nextToken());
int startX = 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(br.readLine());
for (int j = 0; j < m; j++) {
arr[i][j] = Integer.parseInt(st.nextToken());
}
}
st = new StringTokenizer(br.readLine());
Dice dice = new Dice(startY, startX);
for (int i = 0; i < k; i++) {
int order = Integer.parseInt(st.nextToken());
int a = dir(order, dice, n, m, arr);
if(a == 1){
bw.write(dice.diceNum[0]+"\n");
}
}
br.close();
bw.close();
}
private static int dir(int d, Dice dice, int n, int m, int[][] arr){
switch (d){
case 1:
if(dice.nowX + 1 < m){
dice.nowX++;
}else{
return 0;
}
rotates(dice, d, n, m);
solve(dice, arr, arr[dice.nowY][dice.nowX]);
break;
case 2:
if(dice.nowX - 1 >= 0){
dice.nowX--;
}else{
return 0;
}
rotates(dice, d, n, m);
solve(dice, arr, arr[dice.nowY][dice.nowX]);
break;
case 3:
if(dice.nowY - 1 >= 0){
dice.nowY--;
}else{
return 0;
}
rotates(dice, d, n, m);
solve(dice, arr, arr[dice.nowY][dice.nowX]);
break;
case 4:
if(dice.nowY + 1 < n){
dice.nowY++;
}else{
return 0;
}
rotates(dice, d, n, m);
solve(dice, arr, arr[dice.nowY][dice.nowX]);
break;
}
return 1;
}
private static void rotates(Dice dice, int d, int n, int m) {
int[] tmp = dice.diceNum.clone();
switch (d){
case 1:
dice.diceNum[0] = tmp[3];
dice.diceNum[3] = tmp[5];
dice.diceNum[5] = tmp[2];
dice.diceNum[2] = tmp[0];
break;
case 2:
dice.diceNum[0] = tmp[2];
dice.diceNum[3] = tmp[0];
dice.diceNum[5] = tmp[3];
dice.diceNum[2] = tmp[5];
break;
case 3:
dice.diceNum[0] = tmp[4];
dice.diceNum[1] = tmp[0];
dice.diceNum[5] = tmp[1];
dice.diceNum[4] = tmp[5];
break;
case 4:
dice.diceNum[0] = tmp[1];
dice.diceNum[4] = tmp[0];
dice.diceNum[5] = tmp[4];
dice.diceNum[1] = tmp[5];
break;
}
}
private static void solve(Dice dice, int[][] arr, int now){
switch (now){
case 0:
arr[dice.nowY][dice.nowX] = dice.diceNum[5];
break;
default:
dice.diceNum[5] = arr[dice.nowY][dice.nowX];
arr[dice.nowY][dice.nowX] = 0;
}
}
}
문제 링크
14499번 - 주사위 굴리기