https://www.acmicpc.net/problem/14499
처음에 문제를 봤을 때 이해가 한 번에 가지 않아 조금 당황했지만 문제를 이해하고 나면 크게 어렵지는 않은 전형적인 시뮬레이션 문제입니다.
크기가 N * M인 지도가 주어지고, 지도의 각각 칸에 숫자가 쓰여있습니다. 주사위가 처음 놓이는 위치가 주어지고, 해당 위치는 지도에 0이 쓰여있습니다. 주사위는 각 면이 0으로 초기화되어있습니다. (문제에서 주사위 전개도를 보여줄 때 주사위에 숫자가 쓰여있다고 착각해 처음 이해할 때 시간이 조금 걸렸습니다.)
k번에 걸쳐 주사위를 이동시키는 명령이 입력됩니다. 주사위는 지도 위에서 동, 서, 남, 북으로 굴려지며 주사위가 굴러갈 때마다 주사위의 각 면이 바라보는 방향이 바뀝니다. 이때 이동한 위치의 지도에 쓰여있는 수가 0이라면 주사위의 바닥면에 쓰여있는 숫자를 지도에 적고, 0이 아니라면 주사위의 바닥면에 지도에 쓰여있는 숫자를 적은 뒤 지도에 쓰여있던 수는 0으로 바뀝니다. 단 주사위가 지도의 바깥으로 이동한다면 해당 명령은 무시하고 출력도 하지 않습니다.
문제를 이해한 후에는 다른 특이사항 없이 주사위의 각 6개의 면이 네 방향으로 굴려질때 바라보는 방향이 어떻게 바뀌는가만 고려하면 됩니다.
vector<int>를 하나 사용해서 크기를 6으로 초기화합니다. 0~5의 인덱스에 주사위의 각 면이 바라보는 방향을 미리 지정합니다.
vector<int> dice(6); //{0 : 위, 1 : 아래, 2 : 상(북), 3 : 하(남), 4 : 좌(서), 5 : 우(동)}
전역변수로 선언해 초기값은 0이 저장됩니다. (문제에서 가장 처음에 주사위에는 모든 면에 0이 적혀 있다고 명시합니다)
동, 서, 남, 북 방향으로 주사위를 굴릴때마다 주사위의 각 면이 보고 있는 방향을 이전 주사위의 상태를 저장하는 tmp변수와 인덱스를 변경해 바꾸어줍니다.
예를 들어, 명령이 1로 입력되었을 때(동쪽으로 주사위 이동)
상(북), 하(남) 방향을 향하는 주사위의 면은 방향이 바뀌지 않고,
왼(서)쪽를 보고 있던 면은 위쪽으로, // dice[0] = tmp[4];
오른(동)쪽을 보고있던 면은 아래쪽으로, // dice[1] = tmp[5];
아래쪽을 보고있던 면은 왼(서)쪽으로, // dice[4] = tmp[1];
위쪽을 보고있던 면은 오른(동)쪽으로 // dice[5] = tmp[0];
방향이 바뀝니다.
#include<iostream>
#include<vector>
using namespace std;
int n, m, x, y, k;
int board[22][22];
vector<int> dice(6); //(위, 아래, 상, 하, 좌, 우)
bool moveXY(int order)
{
int nx = x;
int ny = y;
if (order == 1) //동
ny++;
else if (order == 2) //서
ny--;
else if (order == 3) //북
nx--;
else
nx++; //남
if (nx < 0 || nx >= n || ny < 0 || ny >= m) return false;
else
{
x = nx;
y = ny;
return true;
}
}
void roll(int order)
{
vector<int> tmp = dice;
if (order == 1) //동
{
dice[0] = tmp[4]; //좌 -> 위
dice[1] = tmp[5]; //우 -> 아래
dice[4] = tmp[1]; //아래 -> 좌
dice[5] = tmp[0]; //위 -> 우
}
else if (order == 2) //서
{
dice[0] = tmp[5];
dice[1] = tmp[4];
dice[4] = tmp[0];
dice[5] = tmp[1];
}
else if (order == 3) //북
{
dice[0] = tmp[3];
dice[1] = tmp[2];
dice[2] = tmp[0];
dice[3] = tmp[1];
}
else
{ //남
dice[0] = tmp[2];
dice[1] = tmp[3];
dice[2] = tmp[1];
dice[3] = tmp[0];
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m >> x >> y >> k;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
cin >> board[i][j];
}
}
int order;
while (k--)
{
cin >> order;
//범위 검사 및 좌표 이동
if (!moveXY(order)) continue;
//주사위 굴리기
roll(order);
if (board[x][y]) //0이 아니라면
{
dice[1] = board[x][y]; //칸의 쓰여있는 수가 주사위 바닥면(1)으로 복사
board[x][y] = 0; //칸의 수는 0
}
else
//0이라면
{
board[x][y] = dice[1]; //칸에 주사위의 바닥면 수 쓰기
}
cout << dice[0]<<"\n"; //주사위의 상단에 쓰여있는 수 출력
}
return 0;
}
'스터디 > 알고리즘 문제풀이' 카테고리의 다른 글
[C++] 백준 2504번 - 괄호의 값 (1) | 2021.06.23 |
---|---|
[C++] Programmers 2020 카카오 인턴십 - 키패드 누르기 (0) | 2021.06.22 |
[C++] 백준 1182번 - 부분수열의 합 (0) | 2021.06.21 |
[C++] 백준 12851번 - 숨바꼭질 2 (0) | 2021.06.02 |
[C++] 백준 1475번 - 방 번호 (0) | 2021.02.20 |