Hello, Freakin world!

[백준 14499번] 주사위 굴리기 본문

알고리즘/PS

[백준 14499번] 주사위 굴리기

johnna_endure 2020. 9. 15. 17:34

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

이 문제도 제겐 약간 까다로운 구현 문제에 속했습니다. 시간이 많다면 푸는데 무리는 없겠지만, 짧은 시간 내에 풀기는 힘들수도 있겠다는 생각이 들었습니다.

 

문제 풀이

 

문제에서는 초기 상태의 주사위의 면마다 번호가 매겨져 있습니다. 

이 문제를 풀기 위한 핵심은 바닥에 위치한 주사위 면을 계속 추적하는 것이 핵심입니다. 

 

어떻게 추적하느냐?

 

주사위의 특성을 이용하면 쉽게 추적이 가능합니다. 주사위 면의 번호가 고맙게도 주사위의 특성을 그대로 따르기 때문에 한 면을 골랐을 때 대응면은 (7-면의 번호)로 추적이 가능합니다.

 

저는 추적할 면을 바닥, 오른쪽옆, 앞면으로 정했습니다.

이 면들은 회전 방향에 따라 서로의 값들로 계산이 가능합니다.

 

예를 들어, 오른쪽으로 회전하는 경우

 

nextBottom(바닥에 오는 면) =  side

nextFront(앞방향에 오는 면) = front 

nextSide(오른쪽 옆 방향의 면) = 7 - bottom

 

위와 같은 수식이 성립합니다. 왼쪽, 오른쪽, 아래 등도 그리 어렵지 않으니 금방 알아낼 수 있을겁니다.

 

면의 위치 추적이 완료됐다면 이제 지도의 값에 따라 규칙대로 주사위의 값을 바꾸는 등 연산을 추가하면 됩니다.

 

...
/*
백준 14499번 - 주사위 굴리기
https://www.acmicpc.net/problem/14499
 */
public class Main {
	static int n,m,k;
	static int[][] map;
	static int[] dice = new int[7];
	public static void main(String[] args) throws IOException {
//		InputReader reader = new InputReader("testcase.txt");
		InputReader reader = new InputReader();
		StringTokenizer st = new StringTokenizer(reader.readLine());
		n = Integer.parseInt(st.nextToken());
		m = Integer.parseInt(st.nextToken());
		int start_row = Integer.parseInt(st.nextToken());
		int start_col = Integer.parseInt(st.nextToken());
		k = Integer.parseInt(st.nextToken());

		map = new int[n][m];
		for (int i = 0; i < n; i++) {
			st = new StringTokenizer(reader.readLine());
			for (int j = 0; j < m; j++) {
				map[i][j] = Integer.parseInt(st.nextToken());
			}
		}

		Queue<Integer> q = new ArrayDeque<>();
		st = new StringTokenizer(reader.readLine());
		for (int i = 0; i < k; i++) {
			q.add(Integer.parseInt(st.nextToken()));
		}

		simulate(start_row, start_col, q);
	}

	private static void simulate(int start_row, int start_col, Queue<Integer> q) {
		int row = start_row; int col = start_col;
		int bottom = 6; int front = 5; int side = 3;
		StringBuilder sb = new StringBuilder();
		while(!q.isEmpty()) {
			int query = q.poll();
			int cur_bottom = bottom; int cur_front = front;
			int cur_side = side;

			//오른쪽으로 굴린다
			if(query == 1) {
				if(!isRange(row, col+1)) continue;
				col++;
				bottom = cur_side;
				side = 7 - cur_bottom;
			}
			//왼쪽으로 굴린다
			if(query == 2) {
				if(!isRange(row, col-1)) continue;
				col--;
				bottom = 7-cur_side;
				side = cur_bottom;
			}
			//위로 굴린다
			if(query == 3) {
				if(!isRange(row-1, col)) continue;
				row--;
				bottom = 7-cur_front;
				front = cur_bottom;
			}
			//아래로 굴린다
			if(query == 4) {
				if(!isRange(row+1, col)) continue;
				row++;
				bottom = cur_front;
				front = 7 - cur_bottom;
			}

			if(map[row][col] == 0) {
				map[row][col] = dice[bottom];
			}else {
				dice[bottom] = map[row][col];
				map[row][col] = 0;
			}
			sb.append(dice[7-bottom]+"\n");
		}
		sb.deleteCharAt(sb.length()-1);
		System.out.println(sb.toString());
	}

	private static boolean isRange(int row, int col) {
		if(row < 0 || row >= n || col < 0 || col >= m) return false;
		return true;
	}


}

class InputReader {
	private BufferedReader br;

	public InputReader() {
		br = new BufferedReader(new InputStreamReader(System.in));
	}

	public InputReader(String filepath) {
		try {
			br = new BufferedReader(new FileReader(filepath));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	public String readLine() throws IOException {
		return br.readLine();
	}
	public int readInt() throws IOException {
		return Integer.parseInt(readLine());
	}
}

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

[백준 11279번] 최대 힙  (0) 2020.09.16
[백준 1927번] 최소 힙  (0) 2020.09.16
[백준 14889번] 스타트와 링크  (0) 2020.09.15
[백준 15686번] 치킨 배달  (0) 2020.09.14
[백준 14502번] 연구소  (0) 2020.09.13
Comments