Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Today
Total
관리 메뉴

Life Engineering

[BOJ 23288] 주사위 굴리기 2 (Java) 본문

Problem Solving

[BOJ 23288] 주사위 굴리기 2 (Java)

흑개 2022. 4. 21. 23:08

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

 

23288번: 주사위 굴리기 2

크기가 N×M인 지도가 존재한다. 지도의 오른쪽은 동쪽, 위쪽은 북쪽이다. 지도의 좌표는 (r, c)로 나타내며, r는 북쪽으로부터 떨어진 칸의 개수, c는 서쪽으로부터 떨어진 칸의 개수이다. 가장 왼

www.acmicpc.net

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

public class Main_BOJ_23288 {
	static int[] dr= {0,1,0,-1};
	static int[] dc= {1,0,-1,0};
	static int[] east= {3,1,0,5,4,2};
	static int[] west= {2,1,5,0,4,3};
	static int[] south= {1,5,2,3,0,4};
	static int[] north= {4,0,2,3,5,1};
	static int N, M, K;
	static int[][] map;
	static int[] dices;
	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());
		K=Integer.parseInt(st.nextToken());
		map=new int[N][M];
		dices=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());
			}
		}
		for (int i=0; i<6; i++) {
			dices[i]=i+1;
		}
		int r=0, c=0, d=0;
		int answer=0;
		for (int i=0; i<K; i++) {
			r+=dr[d];
			c+=dc[d];
			if (r<0 || c<0 || r>=N || c>=M) {
				r-=dr[d]; c-=dc[d];
				d=(d+2)%4;
				r+=dr[d]; c+=dc[d];
			}
			answer+=getScore(r,c);
			d=changeDir(d, map[r][c]);
		}
		System.out.println(answer);

	}

	private static int getScore(int r, int c) {
		int B=map[r][c];
		int C=1;
		boolean[][] visited=new boolean[N][M];
		Queue<int[]> q=new LinkedList<>();
		q.add(new int[] {r,c});
		visited[r][c]=true;
		while (!q.isEmpty()) {
			int[] curr=q.poll();
			for (int i=0; i<4; i++) {
				int nr=curr[0]+dr[i];
				int nc=curr[1]+dc[i];
				if (nr<0 || nc<0 || nr>=N || nc>=M) continue;
				if (!visited[nr][nc] && map[nr][nc]==B) {
					C++;
					q.add(new int[] {nr,nc});
					visited[nr][nc]=true;
				}
			}
		}
		return B*C;
	}
	
	private static int changeDir(int d, int B) {
		int[] temp=new int[6];
		if (d==0) {		
			for (int i=0; i<6; i++) {
				temp[i]=dices[east[i]];
			}
		}
		else if (d==1) {		
			for (int i=0; i<6; i++) {
				temp[i]=dices[south[i]];
			}
		}
		else if (d==2) {		
			for (int i=0; i<6; i++) {
				temp[i]=dices[west[i]];
			}
		}
		else if (d==3) {		
			for (int i=0; i<6; i++) {
				temp[i]=dices[north[i]];
			}
		}
		dices=temp;
		int A=temp[5]; //바닥면
		if (A>B) return (d+1)%4;
		else if (A<B) return (d+3)%4;
		else return d;
	}

}

구현+시뮬레이션+BFS 문제

 

점수를 얻는 것은 getScore 함수로, BFS를 이용해 구현했다. 미방문인 곳 & 현재 위치와 숫자가 같은 곳만 탐색하여 그 횟수를 세주는 식으로 진행했다.

 

주사위를 움직이는 것은 changeDir 함수를 통해 구현했다.

dices 배열의 각 자리를 현재 바라보고 있는 방향으로 매칭시켰다.

즉 0 인덱스: 위쪽 방향, 1 인덱스: 북쪽 방향, 2 인덱스: 동쪽 방향, 3 인덱스: 서쪽 방향, 4 인덱스: 남쪽 방향, 5 인덱스: 바닥 방향 

이렇게 해서 현재 00방향을 바라보고 있는 것이 동서남북으로 움직일 경우 어느 방향을 바라보고 있을 것인가를 생각해서 이 정보를 이용해 east, west, south, north 배열을 만든 뒤 이를 이용해 dices 배열의 값을 적절하게 넣어주었다.