N

(백준 c++)주사위 굴리기2 본문

백준 알고리즘

(백준 c++)주사위 굴리기2

naeunchan 2022. 4. 29. 00:18
728x90
반응형

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

 

23288번: 주사위 굴리기 2

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

www.acmicpc.net

클래스로 주사위를 굴리는 전체 상황을 만들었다.

 

우선 전역변수로는 세로, 가로의 크기인 N, M.

상하좌우 이동할 방향을 나타내는 배열 dx, dy.

최대 20 x 20의 크기를 가지는 board를 선언했다.

 

Dice 클래스.

현재 좌표를 나타내는 x, y.

주사위의 상태를 나타내는 dice로, 처음에는 {1, 3, 4, 5, 2, 6}으로 초기화했다.

이동할 방향을 나타내는 direct로, 0, 1, 2, 3의 값을 가지며 차례대로 상하좌우를 뜻한다.

 

먼저 dice는 자기가 정의하고 싶은대로 면의 위치를 정하면 된다.

필자의 경우는 인덱스의 차례대로

{윗면, 윗면의 오른쪽, 윗면의 왼쪽면, 윗면의 아랫쪽면, 윗면의 윗쪽면, 윗면의 반대편면}으로 정의했다.

 

메소드는 여러개가 있지만 이름만 봐도 유추할 수 있도록 했다.

goEast() ~ goNorth()는 현재 주사위를 각각 동서남북 방향으로 굴리는 것이다.

swap() 함수를 통해 인덱스의 수를 바꿔주면 된다.

 

checkRange() 함수는 매개변수로 받은 x, y 좌표가 보드의 범위를 벗어나는지 확인하는 메소드다.

 

updateXY() 함수는 주사위를 굴린 후 새로운 x, y 좌표를 갱신해주는 메소드다.

 

go() 함수는 주사위를 굴리는 실제 게임의 구현 부분이다.

내부 구현은 어렵지 않기 때문에 차례대로 구현만 제대로 해준다면 30분내로 풀 수 있을 것 같다.

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

int N;
int M;
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
vector<vector<int>> board(20, vector<int>(20, 0));

class Dice{
	private:
		int x = 0;
		int y = 0;
		int dice[6] = {1, 3, 4, 5, 2, 6};
		int direct = 3;
	
	public:
		void goEast() {
			swap(this->dice[0], this->dice[1]);
			swap(this->dice[0], this->dice[2]);
			swap(this->dice[2], this->dice[5]);
		}
		
		void goWest() {
			swap(this->dice[0], this->dice[1]);
			swap(this->dice[1], this->dice[2]);
			swap(this->dice[1], this->dice[5]);
		}
		
		void goSouth() {
			swap(this->dice[0], this->dice[4]);
			swap(this->dice[3], this->dice[4]);
			swap(this->dice[4], this->dice[5]);
		}
		
		void goNorth() {
			swap(this->dice[0], this->dice[3]);
			swap(this->dice[3], this->dice[4]);
			swap(this->dice[3], this->dice[5]);
		}
		
		bool checkRange(int x, int y) {
			if(x >= 0 && x < N && y >= 0 && y < M){
				return true;
			}
			
			return false;
		}
		
		void updateXY(int x, int y){
			this->x = x;
			this->y = y;
		}
		
		int go() {
			int nx = this->x + dx[direct];
			int ny = this->y + dy[direct];
			int A, B, C = 1;
			vector<vector<bool>> visited(N, vector<bool>(M, false));
			queue<pair<int, int>> q;
			
            // 다음 경로 범위 검사
			if(!checkRange(nx, ny)){
				switch(this->direct){
					case 0:
						this->direct = 1;
						break;
						
					case 1:
						this->direct = 0;
						break;
						
					case 2:
						this->direct = 3;
						break;
						
					case 3:
						this->direct = 2;
						break;
				}
				
				nx = this->x + dx[direct];
				ny = this->y + dy[direct];
			}
			
            // 현재 좌표 갱신
			updateXY(nx, ny);
			
            // 방향에 따라 주사위 굴리기
			switch(this->direct){
				case 0:
					this->goNorth();
					break;
				
				case 1:
					this->goSouth();
					break;
				
				case 2:
					this->goWest();
					break;
				
				case 3:
					this->goEast();
					break;
			}
			
            // A, B, C 구하기
			A = this->dice[5];
			B = board[nx][ny];
			
            // C를 구하기 위한 BFS
			q.push({nx, ny});
			visited[nx][ny] = true;
			
			while(!q.empty()){
				int x = q.front().first;
				int y = q.front().second;
				
				q.pop();
				
				for(int i = 0; i < 4; i++){
					int nx = x + dx[i];
					int ny = y + dy[i];
					
					if(checkRange(nx, ny) && !visited[nx][ny] && board[nx][ny] == B){
						q.push({nx, ny});
						visited[nx][ny] = true;
						C++;
					}
				}
			}
			
            // A와 B 결과에 따른 방향 갱신
			if(A > B){
				switch(this->direct){
					case 0:
						this->direct = 3;
						break;
					
					case 1:
						this->direct = 2;
						break;
					
					case 2:
						this->direct = 0;
						break;
					
					case 3:
						this->direct = 1;
						break;
				}
			} else if(A < B){
				switch(this->direct){
					case 0:
						this->direct = 2;
						break;
					
					case 1:
						this->direct = 3;
						break;
					
					case 2:
						this->direct = 1;
						break;
					
					case 3:
						this->direct = 0;
						break;
				}
			}
			
			return B * C;
		}
};

int main() {
	Dice play;
	int K;
	int answer = 0;
	
	cin >> N >> M >> K;
	
	for(int i = 0; i < N; i++){
		for(int j = 0; j < M; j++){
			cin >> board[i][j];
		}
	}
	
	while(K--){
		answer += play.go();
	}
	
	cout << answer;
	
	return 0;
}
728x90
반응형

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

(백준 c++)23290 마법사 상어와 복제  (0) 2022.04.30
(백준 c++)23289 온풍기 안녕!  (0) 2022.04.29
(백준 c++)12100. 2048(Easy)  (0) 2022.04.26
(백준 c++)2470 두 용액  (0) 2021.07.28
(백준 c++)3273 두 수의 합  (0) 2021.07.27