시뮬레이션 문제이다.
다른 풀이를 찾아보니 귀찮아서 시도하지 않은 방법을 써서 코드를 더 예쁘게(?) 써놓은 게 있더라.
내가 한 방법은 무식하고 직관적인 방법..
출발 위치와 진행 방향을 임의로 선정할 수 있다고 했으므로 빈 공간에서 상하좌우로 핀볼을 굴리는 상황을 고려하면 된다.
핀볼의 현재 방향과 부딪히는 블록의 번호를 잘 조합해서 방향을 바꾸는 함수를 만들어 해결.
벽에 부딪힐 경우 핀볼의 좌표를 우선 벽 너머로 설정한 뒤 다음 턴에 범위 안으로 넣어주었다. 이렇게 해야 벽에 부딪히고 방향이 바뀐 채로 블록에 부딪히는 상황을 고려할 수 있었다. (시작위치 (0, 2) 방향: 왼쪽 의 test case)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int T, N, rst;
int map[100][100];
int sx, sy, dir, nx, ny;
int dx[] = { 0, -1, 0, 1, 0 };
int dy[] = { 0, 0, -1, 0, 1 };
void input() {
cin >> N;
memset(map, 0, sizeof(map));
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cin >> map[i][j];
}
}
rst = 0;
}
void holl(int x, int y, int val) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (map[i][j] == val) {
if (x == i && y == j) continue;
nx = i; ny = j; // 새로운 웜홀의 위치
break;
}
}
}
}
int block(int num) {
switch (num) {
case 1:
if (dir == 1) return 3;
if (dir == 2) return 1;
if (dir == 3) return 4;
if (dir == 4) return 2;
case 2:
if (dir == 1) return 4;
if (dir == 2) return 3;
if (dir == 3) return 1;
if (dir == 4) return 2;
case 3:
if (dir == 1) return 2;
if (dir == 2) return 4;
if (dir == 3) return 1;
if (dir == 4) return 3;
case 4:
if (dir == 1) return 3;
if (dir == 2) return 4;
if (dir == 3) return 2;
if (dir == 4) return 1;
case 5:
if (dir == 1) return 3;
if (dir == 2) return 4;
if (dir == 3) return 1;
if (dir == 4) return 2;
}
}
int wall() {
if (dir == 1) return 3;
if (dir == 2) return 4;
if (dir == 3) return 1;
if (dir == 4) return 2;
}
int is_range(int x, int y) {
if (x >= 0 && x < N && y >= 0 && y < N) return true;
return false;
}
void simulation(int cx, int cy) {
int cnt = 0;
while (true) {
nx = cx + dx[dir];
ny = cy + dy[dir];
if (nx == sx && ny == sy || map[nx][ny] == -1) { // 시작 위치로 돌아오거나, 블랙홀을 만났을 경우
rst = max(cnt, rst);
break;
}
if (!is_range(nx, ny)) { // 벽을 만날 경우
cnt++; // 점수 획득
dir = wall(); // 방향은 반대로
cx = nx; cy = ny;
continue;
}
if (map[nx][ny] == 0) { // 빈 공간일 경우, 좌표만 이동
cx = nx; cy = ny;
continue;
}
else if (map[nx][ny] >= 6 && map[nx][ny] <= 10) { // 웜홀을 만날 경우
holl(nx, ny, map[nx][ny]); // nx, ny 를 세팅
cx = nx; cy = ny; // 다른 웜홀로 이동
}
else if (map[nx][ny] >= 1 && map[nx][ny] <= 5) {
cnt++; // 점수 획득
dir = block(map[nx][ny]); // 현재 방향과 부딪힌 블럭 조합으로 다음 방향 획득
cx = nx; cy = ny; // 좌표 이동
}
}
}
void solve() {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
for (int d = 1; d <= 4; d++) {
if (map[i][j] == 0) { // 블록, 웜홀 또는 블랙홀이 있는 위치에서는 출발할 수 없다.
sx = i; sy = j; dir = d;
simulation(sx, sy);
}
}
}
}
}
int main(){
cin >> T;
for (int tc = 1; tc <= T; tc++) {
input();
solve();
cout << "#" << tc << " " << rst << endl;
}
}