문제 정보
백준 ( BOJ ) 14499 주사위 굴리기
문제 풀이 : 시뮬레이션
문제 출처 : https://www.acmicpc.net/problem/14499
문제 풀이
문제에서 핵심은 간단합니다.
map 칸이 0이면 주사위 아랫바닥 수가 map에 복사되고,
0이 아니면 map 칸이 주사위 아랫바닥에 복사되며, map 칸은 0이 됩니다.
다만 주의하셔야 할 문제점이 있는데,
주사위의 x, y 좌표가 주어진다고 하였으나,
사실 y,x 좌표가 주어진다는 겁니다.
세로 크기 N, 가로 크기 M (1 ≤ N, M ≤ 20), 주사위를 놓은 곳의 좌표 x y(0 ≤ x ≤ N-1, 0 ≤ y ≤ M-1),
위를 보시면, x는 세로인 N / y는 가로인 M 에 영향을 받죠..
예시는 x,y가 같은 좌표만 주어졌기에, 잘 풀었지만 틀렸다면 대부분 여기서 틀리셨을 겁니다.
자 그러면 기본 동작을 짜는것은 어렵지 않기에, 주사위를 어떻게 굴려야 할지 알아보겠습니다.
맨 처음엔 각 주사위 눈금을 만들어 left,right,up,down 으로 연결시키려 하였지만
그렇게 하면 안됩니다.
(같은 의미로, x칸의 left는 y, 이런식으로도 하면 안됩니다. )
왜냐하면 주사위가 계속 굴러가기때문에, 동-서-남-북 방향으로 굴렀을떄의 값이 모두 다르기 때문입니다.
그럼 어떻게 해야하나?
주사위가 left, right, up, down 시 아에 배열값을 바꿔 줘 버립니다.
예를들면,
1
4 2 3
6
5
이런 주사위가 있다고 생각 해 봅시다.
이 주사위를 왼쪽으로 굴린다면 위치가 바뀔텐데요,
이걸 다시
1
4 2 3
6
5
로 만들어 줍니다.
여기서 주사위의 이동은 다음과 같습니다.
1->2 2->6 3(제자리) 4->1 5(제자리) 6->4
(해당 과정은 직접 그림 그리면서 해보시는게 가장 빠릅니다.)
이런식으로 1번값은 2번으로 옮기고, 2번값은 6번으로,
3,5번은 그대로 두고, 4번값은 1로, 6번값은 4번으로 옮기면
다시 원래순서에 맞게 주사위 배열이 될 겁니다.
즉, 언제나 밑에칸은 1번이고, 위에칸은 6번 이 되는겁니다.
이걸 각 방향별로 만들어 주시면 됩니다.
저는 편의를 위하여 DICE라는 클래스를 만들어서 클래스 안에서 처리 하도록 만들었습니다.
void left() {
queue<int> q;
for (int i = 0; i < 6; i++) {
q.push(number[i]);
}
number[1] = q.front();
q.pop();
number[5] = q.front();
q.pop();
q.pop();
number[0] = q.front();
q.pop();
q.pop();
number[3] = q.front();
q.pop();
// 1->2 2->6 3 4->1 5 6->4
}
주사위는 큐에 넣어서 돌렸습니다.
주의할 케이스
N,M (1 ≤ N, M ≤ 20)
x y(0 ≤ x ≤ N-1, 0 ≤ y ≤ M-1),
K (1 ≤ K ≤ 1,000)
동쪽은 1, 서쪽은 2, 북쪽은 3, 남쪽은 4로 주어진다.
지도 밖으로 나가려하면 무시한다.
N,M 크기도 작고, k 갯수도 작기 때문에 시간초과나, 오버플로우가 발생할 일은 없습니다.
그럼 이제 주의해야할 건 최소값이죠.
N,M 이 1 이상이기에 (1,1) 지도가 생길 수 있습니다.
그러나 이건 아래의 지도 밖으로 나가려하면 무시한다
와 맞물려 고려 하지 않아도 됩니다.
또 한가지 주의할 점은, N,M 은 1 이상의 정수로 주어지지만,
x,y는 우리가 흔히 프로그래밍 할때 사용하는 0부터 시작하는 정수 라는 점만
주의 해 주시면 될 거 같습니다.
문제 코드
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
class DICE {
public:
void left() {
queue<int> q;
for (int i = 0; i < 6; i++) {
q.push(number[i]);
}
number[1] = q.front();
q.pop();
number[5] = q.front();
q.pop();
q.pop();
number[0] = q.front();
q.pop();
q.pop();
number[3] = q.front();
q.pop();
// 1->2 2->6 3 4->1 5 6->4
}
void right() {
queue<int> q;
for (int i = 0; i < 6; i++) {
q.push(number[i]);
}
number[3] = q.front();
q.pop();
number[0] = q.front();
q.pop();
q.pop();
number[5] = q.front();
q.pop();
q.pop();
number[1] = q.front();
q.pop();
// 1->4 2->1 3x 4->6 5 6->2
}
void up() {
queue<int> q;
for (int i = 0; i < 6; i++) {
q.push(number[i]);
}
number[4] = q.front();
q.pop();
q.pop();
number[0] = q.front();
q.pop();
q.pop();
number[5] = q.front();
q.pop();
number[2] = q.front();
q.pop();
// 1->5 2 3->1 4 5->6 6->3
}
void down() {
queue<int> q;
for (int i = 0; i < 6; i++) {
q.push(number[i]);
}
number[2] = q.front();
q.pop();
q.pop();
number[5] = q.front();
q.pop();
q.pop();
number[0] = q.front();
q.pop();
number[4] = q.front();
// 1->3 2 3->6 4 5->1 6->5
}
int getDown() {
return number[0];
}
void setDown(int a) {
number[0] = a;
}
int getUp() {
return number[5];
}
DICE() {
for (int i = 0; i < 6; i++)
number.push_back(0);
}
private:
vector<int> number;
};
int main() {
int mapX, mapY, diceX, diceY, n;
int temp;
cin >> mapY >> mapX >> diceY >> diceX >> n;
vector<vector<int>> map(mapY, vector<int>(mapX, 0));
for (int i = 0; i < mapY; i++) {
for (int j = 0; j < mapX; j++) {
cin >> temp;
map[i][j] = temp;
}
}
DICE dice;
for (int i = 0; i < n; i++) {
int error = 0;
cin >> temp;
switch(temp) {
case 1:
if (diceX == mapX - 1) {
error = 1;
}
else {
diceX++;
dice.right();
}
break;
case 2:
if (diceX == 0) {
error = 1;
}
else {
dice.left();
diceX--;
}
break;
case 3:
if (diceY == 0) {
error = 1;
}
else {
dice.up();
diceY--;
}
break;
case 4:
if (diceY == mapY - 1) {
error = 1;
}
else {
dice.down();
diceY++;
}
break;
}
if (error==0){
cout << dice.getUp() << endl;
if (map[diceY][diceX] == 0)
map[diceY][diceX] = dice.getDown();
else {
dice.setDown(map[diceY][diceX]);
map[diceY][diceX] = 0;
}
/*
for (int i = 0; i < mapY; i++) {
for (int j = 0; j < mapX; j++) {
cout << map[i][j] << " ";
}
cout << endl;
}*/
}
}
return 0;
}