하루에 한 문제

[BOJ-14499] 주사위 굴리기 -Java 본문

알고리즘/백준

[BOJ-14499] 주사위 굴리기 -Java

dkwjdi 2021. 1. 27. 23:03

https://www.acmicpc.net/problem/14499

 

14499번: 주사위 굴리기

첫째 줄에 지도의 세로 크기 N, 가로 크기 M (1 ≤ N, M ≤ 20), 주사위를 놓은 곳의 좌표 x y(0 ≤ x ≤ N-1, 0 ≤ y ≤ M-1), 그리고 명령의 개수 K (1 ≤ K ≤ 1,000)가 주어진다. 둘째 줄부터 N개의 줄에 지도

www.acmicpc.net

package 시뮬레이션_review;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class boj_14499_주사위굴리기 {
	static int N,M,x,y,K,map[][],move[],dice[];
	static int dx[]= {0,0,0,-1,1};
	static int dy[]= {0,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());
		StringBuilder sb= new StringBuilder();
		
		N=Integer.parseInt(st.nextToken());
		M=Integer.parseInt(st.nextToken());
		x=Integer.parseInt(st.nextToken());
		y=Integer.parseInt(st.nextToken());
		K=Integer.parseInt(st.nextToken());
		
		map= new int[N][M];
		move=new int[K];
		dice=new int[6];
		
		//맵 
		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<K; i++) {
			move[i]=Integer.parseInt(st.nextToken());
		}
		
		solve(sb);
		System.out.println(sb.toString());
		
	}
	private static void solve(StringBuilder sb) {
		
		for(int i=0; i<K; i++) { //주사위의 이동만큼
			int dir=move[i];
			
			//x,y좌표 이동
			int nx=x+dx[dir];
			int ny=y+dy[dir];
			
			if(nx<0 || ny<0 || nx>=N || ny>=M) continue; //범위넘어가면 skip
			
			x=nx; //범위 안넘어가니까 x,y바꿔주기
			y=ny;
			
			if(dir==1 || dir==2) { //1번 2번은  위 좌 아래 우 앞 뒤 
				int []copyDice= {dice[0],dice[3],dice[5],dice[2],dice[4],dice[1]};
				rollTheDice(copyDice,dir);
				rearrange(copyDice,dir);
				
			}
			else { //3번 4번은 앞 위 뒤 아래 좌 우 
				int []copyDice= {dice[4],dice[0],dice[1],dice[5],dice[3],dice[2]};
				rollTheDice(copyDice,dir);
				rearrange(copyDice,dir);
			}
			
			if(map[x][y]==0) { //이동한 칸이 0 이면 -> 주사위 바닥면에 쓰인수가 칸에 복사
				map[x][y]=dice[5];
			}
			else { //이동한칸이 0이 아니면 칸의 수가 주사위로 들어가고 칸은 0
				dice[5]=map[x][y];
				map[x][y]=0;
			}
			sb.append(dice[0]+"\n");
		}
		
	}
	private static void rearrange(int[] copyDice, int dir) {
		// 원래 주사위 ->>> 위 뒤 오 왼 앞 아래   
		if(dir==1 || dir==2) { //1번 2번은  위 좌 아래 우 앞 뒤  
			dice[0]=copyDice[0];
			dice[1]=copyDice[5];
			dice[2]=copyDice[3];
			dice[3]=copyDice[1];
			dice[4]=copyDice[4];
			dice[5]=copyDice[2];
		}
		else {//3번 4번은 앞 위 뒤 아래 좌 우
			dice[0]=copyDice[1];
			dice[1]=copyDice[2];
			dice[2]=copyDice[5];
			dice[3]=copyDice[4];
			dice[4]=copyDice[0];
			dice[5]=copyDice[3];
		}
	}
	private static void rollTheDice(int[] copyDice, int dir) {
		if(dir==1||dir==3) { //1번, 3번은 오른쪽으로 
			int num=copyDice[3];
			for(int i=3; i>0; i--) copyDice[i]=copyDice[i-1];
			copyDice[0]=num;
		}
		else { //2번 ,4번은 왼쪽으로
			int num=copyDice[0];
			for(int i=0; i<3; i++) copyDice[i]=copyDice[i+1];
			copyDice[3]=num;
		}
	}
	

}

소요시간 : 55분

 

처음에 어떻게 풀지 생각하고 규칙 찾는데 A4용지 한 장을 빼곡하게 사용했습니다.

 

일단 푼 방법을 설명해보자면 

 

1   2    3   4    5   6

위  뒤  우  좌  앞  밑  -> 문제처럼 dice배열을 만들어 줍니다.

 

그리고 1번과 2번으로 주사위를 굴리게 되면 앞,뒤는 고정이고,  위, 좌, 밑, 우 만 바뀌게 됩니다.

마찬가지로 3번과 4번은 좌,우는 고정이고  앞, 위, 뒤, 밑 만 바뀌게 됩니다.

 

그리고 1번과 3번은 고정인 것을 빼고 나머지를 오른쪽으로 한 칸씩 밀어주면 됩니다.

또 2번과 4번은 고정인것을 빼고 나머지를 왼쪽으로 한 칸씩 밀어주면 됩니다.

 

직접 그려보시면 무슨 소린지 쉽게 이해하실 수 있습니다.

 

그래서 원래 dice배열을    1,2번이냐 vs 3,4번이냐에 따라 

1,2번  위 좌 밑 오   앞 뒤 (고정)

3,4번  앞 위 뒤 밑   좌 우 (고정)

처럼 copyDice를 만들게 됩니다.

copyDice를 만드는 이유는 위에처럼 주사위를 바꾸게 되면 그림처럼 고정 2개를 빼고 나머지를 왼쪽이나, 오른쪽으로 밀어주면 주사위를 굴린 효과를 얻을 수 있기 때문입니다.

위의 내용처럼 주사위를 굴린 효과를 얻은 후 다시 Dice배열에 원래대로 넣어줍니다!

 

위를 토대로 큰 로직을 보게 되면 

 

 

1. x,y좌표를 확인하고 갈 수 있다면 주사위를 굴린다. (rollTheDice 함수 이용)

2. copyDice를 원래의 주사위로 돌려준다 (rearrange 함수 이용)

3. 현재 주사위가 위치한 칸의 숫자를 확인한다.

   3-1 만약 주사위가 위치한 칸이 0이라면 주사위 바닥면의 수를 칸에 복사한다.

   3-2 만약 주사위가 위치한 칸이 0이 아니라면 칸의 수가 주사위의 바닥면으로 들어가고 칸은 0으로 바꿔준다.

4. 주사위 윗부분의 숫자 출력

 

 

그림으로 그려가면서 할 때는 쉬웠는데 뭔가 설명하려고 하니까 조금 어렵네요...

직접 그려보면서 하신다면 금방 이해하실 거라고 생각합니다!

 

 

 

 

'알고리즘 > 백준' 카테고리의 다른 글

[BOJ-14501] 퇴사 -Java  (3) 2021.01.29
[BOJ-13458] 시험 감독 -Java  (0) 2021.01.29
[BOJ-2573] 빙산 -Java  (0) 2021.01.24
[BOJ-3190] 뱀 -Java  (1) 2021.01.08
[BOJ-16637] 괄호추가하기 -Java  (1) 2020.12.30
Comments