N
(백준 c++)주사위 굴리기2 본문
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;
}
'백준 알고리즘' 카테고리의 다른 글
(백준 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 |