문제 풀이 날짜: 2023.09.07
포스트 작성일: 2023.09.11

 

* 학습 목적으로 작성하는 글입니다. 풀이가 정석적이지 못할 수도 있습니다.

 

문제 출처

백준 온라인 저지 14499번: 주사위 굴리기 (골드4)

 

키워드

구현, 시뮬레이션

 

풀이 접근법

  • 주사위를 굴렸을 때 다음 눈에 해당하는 좌표가 어디인지를 구하는 게 중요하며, 구현하기도 쉽지 않다. 배열 값은 물리적으로(?) 떨어져 있어도 실제 주사위 상으로는 이어져있기 때문이다.
  • 여기서 주사위 배열을 1차원 배열로 선언하고, 각 방향으로 밀었을 때 숫자가 어떻게 변화하는 지를 switch문으로 대입해준다. 동, 서, 남, 북 4가지 방향으로 주사위를 밀었을 때 주사위의 어느 눈이 어느 위치로 옮겨가는 지만 지정해주면 된다. (경우의 수가 많지 않기 때문에 충분히 하드코딩을 시도해볼 수 있다.)
  • 주의1 : 범위를 벗어나지 않고 굴릴 수 있는 경우에만 주사위 값을 옮겨주어야 하며, 그 때에만 출력을 진행해야 한다.
  • 주의2 : 입력 표기가 (x, y)이지만 사실상 (row, col) 순서로 들어온다!!
    • 따라서 row에 x를, col에 y를 대입하거나 입력 순서를 반대를 받자.

 

코드

import java.awt.Point;
import java.io.*;
import java.util.*;

public class Main {

	private static final int UPPER = 3;
	private static final int LOWER = 6;
	
	private static int N;
	private static int M;
		
	private static int[] dice;
	private static int[][] map;
	
	private static int[] dr = {0, 0, -1, 1}; //동, 서, 북, 남
	private static int[] dc = {1, -1, 0, 0};
	
	private static StringBuilder sb = new StringBuilder();
	
	public static void main(String[] args) 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());
		int y = Integer.parseInt(st.nextToken());
		int x = Integer.parseInt(st.nextToken());
		int K = Integer.parseInt(st.nextToken());
		
		map = new int[N][M];
		dice = new int[LOWER + 1]; //인덱스 0은 사용하지 않음, 처음엔 모두 0
		
		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());
			}
		}
		
		//명령어 받기 
		int mapR = y;
		int mapC = x;
		st = new StringTokenizer(br.readLine(), " ");
		for(int i = 0; i < K; i++) {
			int dir = Integer.parseInt(st.nextToken());
			
			Point moved = moveDice(dir, mapR, mapC);
			if(moved != null) { //주사위를 굴렸다면 지도 좌표 갱신
				mapR = moved.y;
				mapC = moved.x;
			}
		}
		
		System.out.print(sb);
	}

	private static Point moveDice(int dir, int mapR, int mapC) {
		int nr = mapR + dr[dir - 1];
		int nc = mapC + dc[dir - 1];
		
		if(!isValid(nr, nc)) {
			return null;
		}
		
		//굴릴 수 있다면 주사위의 방향을 바꿔준다.
		int temp = dice[UPPER];
		
		switch(dir) {
		case 1:
			dice[3] = dice[4];
			dice[4] = dice[6];
			dice[6] = dice[2];
			dice[2] = temp;
			break;
		case 2:
			dice[3] = dice[2];
			dice[2] = dice[6];
			dice[6] = dice[4];
			dice[4] = temp;
			break;
		case 3:
			dice[3] = dice[5];
			dice[5] = dice[6];
			dice[6] = dice[1];
			dice[1] = temp;
			break;
		case 4:
			dice[3] = dice[1];
			dice[1] = dice[6];
			dice[6] = dice[5];
			dice[5] = temp;
			break;
		}
		
		if(map[nr][nc] == 0) {
			map[nr][nc] = dice[LOWER];
		} else {
			//0이 아닌 경우에는 칸에 쓰여 있는 수가 주사위의 바닥면으로 복사되며, 
			//칸에 쓰여 있는 수는 0이 된다.
			dice[LOWER] = map[nr][nc];
			map[nr][nc] = 0;
		}
		
		//주의: 굴릴 수 없다면 출력하지 않는다.
		sb.append(dice[UPPER]).append("\n");

		return new Point(nc, nr);
	}

	private static boolean isValid(int r, int c) {
		return (r > -1 && c > -1 && r < N && c < M);
	}
}

 

참고한 링크

https://loosie.tistory.com/763
https://developer-ellen.tistory.com/118

+ Recent posts