반응형
[모의 SW 역량테스트] 핀볼 게임
1. 이해하기
- 게임판 위에서는 작은 핀볼 하나가 상, 하, 좌, 우 중 한 방향으로 움직인다.
- 핀볼은 블록이나 웜홀 또는 블랙홀을 만나지 않는 한 현재 방향을 유지하며 움직인다.
- 핀볼이 블록의 수평면이나 수직면을 만날 경우 방향을 바꿔 반대 방향으로 돌아오고, 경사면을 만날 경우에는 직각으로 진행 방향이 꺾이게 된다.
- 핀볼은 벽을 만날 경우에도 반대 방향으로 돌아온다.
- 웜홀에 빠지면 동일한 숫자를 가진 다른 반대편 웜홀로 빠져 나오게 되며 진행방향은 그대로 유지된다.
- 핀볼이 블랙홀을 만나면, 핀볼이 사라지게 되어 게임은 끝난다.
- 게임은 핀볼이 출발 위치로 돌아오거나, 블랙홀에 빠질 때 끝나게 된다.
- 점수는 벽이나 블록에 부딪힌 횟수가 된다.
- 게임에서 얻을 수 있는 점수의 최댓값을 구하는 문제.
- 완전탐색+시뮬레이션 문제이다.
2. 구현하기
-
구슬의 이동방향으로 움직이고 그때의 상황을 체크한다.
void move(int sx, int sy) { ball.p.x+=dx[ball.dir]; ball.p.y+=dy[ball.dir]; check_location(sx,sy); }
-
상황별로 알맞게 핀볼의 상태를 바꿔준다.
- 벽이나 블록에 부딪히면 점수를 증가한다.
- 각 맵의 상태에 맞게 핀볼의 상태를 바꿔준다.
- 웜홀에 들어갔을때, 다음 웜홀을 구하는 조건식을 잘 짜야한다.
bool out_of_bound() { return ball.p.x < 0 or ball.p.x >= N or ball.p.y < 0 or ball.p.y >= N; } void check_location(int sx, int sy) { if(out_of_bound()) { if(ball.dir == 0) ball.dir = 1; else if(ball.dir == 1) ball.dir = 0; else if(ball.dir == 2) ball.dir = 3; else if(ball.dir == 3) ball.dir = 2; ball.score++; } else if(map[ball.p.x][ball.p.y] == 1) { if(ball.dir == 0) ball.dir = 1; else if(ball.dir == 1) ball.dir = 3; else if(ball.dir == 2) ball.dir = 0; else if(ball.dir == 3) ball.dir = 2; ball.score++; } else if(map[ball.p.x][ball.p.y] == 2) { if(ball.dir == 0) ball.dir = 3; else if(ball.dir == 1) ball.dir = 0; else if(ball.dir == 2) ball.dir = 1; else if(ball.dir == 3) ball.dir = 2; ball.score++; } else if(map[ball.p.x][ball.p.y] == 3) { if(ball.dir == 0) ball.dir = 2; else if(ball.dir == 1) ball.dir = 0; else if(ball.dir == 2) ball.dir = 3; else if(ball.dir == 3) ball.dir = 1; ball.score++; } else if(map[ball.p.x][ball.p.y] == 4) { if(ball.dir == 0) ball.dir = 1; else if(ball.dir == 1) ball.dir = 2; else if(ball.dir == 2) ball.dir = 3; else if(ball.dir == 3) ball.dir = 0; ball.score++; } else if(map[ball.p.x][ball.p.y] == 5) { if(ball.dir == 0) ball.dir = 1; else if(ball.dir == 1) ball.dir = 0; else if(ball.dir == 2) ball.dir = 3; else if(ball.dir == 3) ball.dir = 2; ball.score++; } else if(6 <= map[ball.p.x][ball.p.y] and map[ball.p.x][ball.p.y] <= 10) { int num = map[ball.p.x][ball.p.y]-6; int nx,ny; for(int i = 0; i < 2; i++) { if(hole[num][i].x != ball.p.x or hole[num][i].y != ball.p.y) { nx = hole[num][i].x; ny = hole[num][i].y; break; } } ball.p.x = nx; ball.p.y = ny; } else if(map[ball.p.x][ball.p.y] == -1) ball.p.x = ball.p.y = -1; else if(sx == ball.p.x and sy == ball.p.y) ball.p.x = ball.p.y = -1; }
-
맵의 비어있는 부분에 핀볼을 4가지 방향으로 모두 넣어보면서 게임에서 얻을 수 있는 점수의 최댓값을 구한다.
int solve() { int ret = 0; for(int i = 0; i < N; i++) { for(int j = 0; j < N; j++) { if(map[i][j] != 0) continue; for(int d = 0; d < 4; d++) { ball.p = {i,j}; ball.dir = d; ball.score = 0; while(1) { if(ball.p.x == -1 and ball.p.y == -1) break; move(i,j); } ret = max(ret,ball.score); } } } return ret; }
3. 전체 코드
#include <iostream>
#include <vector>
using namespace std;
struct Point{
int x,y;
};
struct Ball{
Point p;
int dir,score;
} ball;
int map[100][100];
vector<Point> hole[5];
int dx[] = {-1,1,0,0};
int dy[] = {0,0,-1,1};
int N;
bool out_of_bound() {
return ball.p.x < 0 or ball.p.x >= N or ball.p.y < 0 or ball.p.y >= N;
}
void check_location(int sx, int sy) {
if(out_of_bound()) {
if(ball.dir == 0) ball.dir = 1;
else if(ball.dir == 1) ball.dir = 0;
else if(ball.dir == 2) ball.dir = 3;
else if(ball.dir == 3) ball.dir = 2;
ball.score++;
} else if(map[ball.p.x][ball.p.y] == 1) {
if(ball.dir == 0) ball.dir = 1;
else if(ball.dir == 1) ball.dir = 3;
else if(ball.dir == 2) ball.dir = 0;
else if(ball.dir == 3) ball.dir = 2;
ball.score++;
} else if(map[ball.p.x][ball.p.y] == 2) {
if(ball.dir == 0) ball.dir = 3;
else if(ball.dir == 1) ball.dir = 0;
else if(ball.dir == 2) ball.dir = 1;
else if(ball.dir == 3) ball.dir = 2;
ball.score++;
} else if(map[ball.p.x][ball.p.y] == 3) {
if(ball.dir == 0) ball.dir = 2;
else if(ball.dir == 1) ball.dir = 0;
else if(ball.dir == 2) ball.dir = 3;
else if(ball.dir == 3) ball.dir = 1;
ball.score++;
} else if(map[ball.p.x][ball.p.y] == 4) {
if(ball.dir == 0) ball.dir = 1;
else if(ball.dir == 1) ball.dir = 2;
else if(ball.dir == 2) ball.dir = 3;
else if(ball.dir == 3) ball.dir = 0;
ball.score++;
} else if(map[ball.p.x][ball.p.y] == 5) {
if(ball.dir == 0) ball.dir = 1;
else if(ball.dir == 1) ball.dir = 0;
else if(ball.dir == 2) ball.dir = 3;
else if(ball.dir == 3) ball.dir = 2;
ball.score++;
} else if(6 <= map[ball.p.x][ball.p.y] and map[ball.p.x][ball.p.y] <= 10) {
int num = map[ball.p.x][ball.p.y]-6;
int nx,ny;
for(int i = 0; i < 2; i++) {
if(hole[num][i].x != ball.p.x or hole[num][i].y != ball.p.y) {
nx = hole[num][i].x; ny = hole[num][i].y;
break;
}
}
ball.p.x = nx; ball.p.y = ny;
} else if(map[ball.p.x][ball.p.y] == -1) ball.p.x = ball.p.y = -1;
else if(sx == ball.p.x and sy == ball.p.y) ball.p.x = ball.p.y = -1;
}
void move(int sx, int sy) {
ball.p.x+=dx[ball.dir]; ball.p.y+=dy[ball.dir];
check_location(sx,sy);
}
int solve() {
int ret = 0;
for(int i = 0; i < N; i++) {
for(int j = 0; j < N; j++) {
if(map[i][j] != 0) continue;
for(int d = 0; d < 4; d++) {
ball.p = {i,j}; ball.dir = d; ball.score = 0;
while(1) {
if(ball.p.x == -1 and ball.p.y == -1) break;
move(i,j);
}
ret = max(ret,ball.score);
}
}
}
return ret;
}
void input() {
for(int i = 0; i < 5; i++) hole[i].clear();
cin >> N;
for(int i = 0; i < N; i++) {
for(int j = 0; j < N; j++) {
cin >> map[i][j];
if(6 <= map[i][j] and map[i][j] <= 10) {
hole[map[i][j]-6].push_back({i,j});
}
}
}
}
int main() {
int T;
cin >> T;
for(int t = 1; t <= T; t++) {
input();
cout << '#' << t << ' ' << solve() << '\n';
}
return 0;
}
'알고리즘 > SW Expert Academy' 카테고리의 다른 글
[SWEA 1798] 범준이의 제주도 여행계획 (0) | 2020.05.13 |
---|---|
[SWEA] 7699번 수지의 수지 맞는 여행 (0) | 2020.03.03 |
[모의 SW 역량테스트] 5648. 원자 소멸 시뮬레이션 (0) | 2019.10.19 |
[모의 SW 역량테스트] 5644. 무선 충전 (0) | 2019.10.19 |
[모의 SW 역량테스트] 5658. 보물상자 비밀번호 (0) | 2019.10.19 |