[SWEA] 5650. 핀볼 게임

gyeong·2021년 4월 19일
0

PS

목록 보기
36/46

문제 접근

시뮬레이션 문제이다.
다른 풀이를 찾아보니 귀찮아서 시도하지 않은 방법을 써서 코드를 더 예쁘게(?) 써놓은 게 있더라.

  1. 웜홀 정보를 구조체로 따로 저장
  2. 핀볼이 진행하는 방향에서 1~5번 블록을 만날 시 어떻게 꺾이는지 배열에 미리 저장

내가 한 방법은 무식하고 직관적인 방법..

출발 위치와 진행 방향을 임의로 선정할 수 있다고 했으므로 빈 공간에서 상하좌우로 핀볼을 굴리는 상황을 고려하면 된다.

핀볼의 현재 방향과 부딪히는 블록의 번호를 잘 조합해서 방향을 바꾸는 함수를 만들어 해결.
벽에 부딪힐 경우 핀볼의 좌표를 우선 벽 너머로 설정한 뒤 다음 턴에 범위 안으로 넣어주었다. 이렇게 해야 벽에 부딪히고 방향이 바뀐 채로 블록에 부딪히는 상황을 고려할 수 있었다. (시작위치 (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;
	}
}
profile
내가 보려고 만든 벨로그

0개의 댓글