
시뮬레이션 유형의 골드 이상 난도를 가진 문제는 공통점이 있습니다.
시뮬레이션 유형은 반드시 문제를 읽으면서 줄치는 것 뿐만 아니라 자기 자신의 문장으로 새롭게 조건을 정리해서 쓰는 것이 좋습니다.
문제 조건은 다음과 같습니다.
(r, c)로 표현.(y, x) 데카르트 좌표계를 애용합니다.(x, y)가 아니라 (y, x)로 좌표를 나타내야만 AC가 가능합니다. 1, 서쪽 2, 북쪽 3, 남쪽 4 → d[4][2] = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}}0 임 → 주사위 밑면 숫자가 지도에 복사.0 아님 → 지도 숫자가 주사위 밑면에 복사, 지도 숫자는 0으로 변경.boundaryException)은 무시.문제는 복잡했지만, 위 여섯 줄로 간단하게 정리할 수 있습니다.
주사위 이동과 경계조건 검사 그리고 매 이동 때 해야하는 작업이 간단해 쉬운 문제로 바뀝니다.
주사위를 동, 서, 남, 북으로 이동할 때 어떤 면이 어떻게 바뀌어야 하는지 꼭 생각해보세요.
주사위를 구현하는 방법은 여러가지 있습니다.
3차원 배열을 쓴다.
→ 떠올리지도 마세요.
구조체를 쓴다.
→ 제가 사용한 방법입니다. 코드 가독성이 훨씬 좋아지고 메모리 낭비도 없어 좋아하는 방법입니다.
6칸짜리 1차원 배열을 쓴다.
#include <cstdio>
typedef struct Dice {
int up = 0, down = 0;
int front = 0, back = 0;
int left = 0, right = 0;
} Dice;
Dice dice;
int N, M, X, Y, K, map[20][20];
constexpr int d[4][2] = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
void roll(int op) {
int tmp = dice.down;
switch(op) {
case 0: // east
dice.down = dice.right;
dice.right = dice.up;
dice.up = dice.left;
dice.left = tmp;
break;
case 1: // west
dice.down = dice.left;
dice.left = dice.up;
dice.up = dice.right;
dice.right = tmp;
break;
case 2: // north
dice.down = dice.back;
dice.back = dice.up;
dice.up = dice.front;
dice.front = tmp;
break;
case 3: // south
dice.down = dice.front;
dice.front = dice.up;
dice.up = dice.back;
dice.back = tmp;
break;
}
}
int main() {
scanf("%d %d %d %d %d", &N, &M, &Y, &X, &K);
for (int y = 0; y < N; ++y)
for (int x = 0; x < M; ++x)
scanf("%d", &map[y][x]);
int ny, nx, op;
for (int i = 0; i < K; ++i) {
scanf("%d", &op);
op--;
ny = Y + d[op][0], nx = X + d[op][1];
// Boundary exception
if (N <= ny || ny < 0 || M <= nx || nx < 0) continue;
roll(op);
if (map[ny][nx]) {
dice.down = map[ny][nx];
map[ny][nx] = 0;
}
else map[ny][nx] = dice.down;
Y = ny, X = nx;
printf("%d\n", dice.up);
}
}
