알고리즘 공부/C++

SWEA 5650번 [모의 SW 역량테스트] 핀볼 게임 구현, 시뮬레이션

마달랭 2024. 8. 19. 16:57
반응형

리뷰

2D 시뮬레이션 구현 문제, 범위를 벗어난 조건을 만났을때 잘 처리해 주어야 한다.

 

문제 풀이

  1. init과 input, solution 세가지 구역으로 나누어 풀었다.
  2. init 함수에서는 ans값을 0으로 초기화, 웜홀 정보를 초기화 해주었다.
  3. input에서는 n값을 받고, n * n크기의 맵을 초기화, 만약 맵에서 6이상이 수가 있다면 웜홀을 초기화 해주었다.
  4. solution 함수에서는 맵 전체에서 0인 값을 만난다면 4방향으로 simulation을 돌려주는 브루트포스 역할
  5. simulation 함수에서는 실제로 핀볼이 2D 맵에서 왔다갔다 하고 얻은 점수를 출력해 준다.
  6. 핀볼이 시뮬레이션을 통해 얻은 가장 높은 값을 출력해 주면 된다.

 

참고 사항

simulation 함수 상세 내용

  1. 핀볼이 시작되는 좌표와 현재 핀볼의 방향을 매개변수로 받아온다.
  2. 각각을 nx, ny, nd 로 새로 초기화 해주고 점수를 나타낼 cnt 변수를 0으로 초기화 해준다.
  3. 무한루프를 실행하여 현재 진행방향으로 nx, ny 값을 알맞게 진행시켜 준다.
  4. 벽을 만난 경우를 맵 범위를 벗어난 상태로 인지하여 가장 먼저 조건을 만들어 주었다. 만약 맵 범위 밖으로 나갔을 경우 다시 이전 위치로 돌려놓은 뒤 방향을 반대로 설정해 주었다. 좌 ↔ 우, 상 ↔ 하 이런 식으로, 점수 1 증가
  5. 만약 현재 위치가 -1일 경우 블랙홀을 만난 경우이므로 break 처리해 준다.
  6. 만약 현재 위치가 초기에 매개변수로 받아온 x, y라면 처음 위치로 돌아온 경우이므로 break 처리해 준다.
  7. 만약 6 이상의 숫자를 만난 경우 웜홀을 만난 것이다. 각 반대 위치로 순간이동을 시켜준다.
  8. 만약 1 ~ 5 사이의 숫자를 만난 경우 블럭을 만난 것이다. 각 블럭에 알맞게 방향을 변환시켜 준다. 점수 1 증가
  9. while문이 break 되었을 경우 그 동안 모은 cnt 값을 리턴해 주고 최대값을 갱신해 준다.

 

정답 코드

#include<iostream>
#include<vector>

using namespace std;

int tc, n, w, ans;

int lst[101][101];
int dx[] = { -1, 1, 0, 0 };
int dy[] = { 0, 0, -1, 1 };

int blocks[6][4] = {
	{0, 0, 0, 0},
	{1, 3, 0, 2},
	{3, 0, 1, 2},
	{2, 0, 3, 1},
	{1, 2, 3, 0},
	{1, 0, 3, 2}
};

struct WH {
	int x, y;
};

vector<vector<WH>> worm;

void init() {
	ans = 0;
	for (auto& w : worm ) w.clear();
	worm.resize(11);
}

void input() {
	cin >> n;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cin >> lst[i][j];
			if (lst[i][j] >= 6) {
				worm[lst[i][j]].push_back({ i, j });
			}
		}
	}
}

int sumulation(int x, int y, int dir) {
	int nx = x, ny = y, nd = dir, cnt = 0;
	while (1) {
		nx += dx[nd];
		ny += dy[nd];

		// 벽을 만난 경우
		if (nx < 0 || ny < 0 || nx >= n || ny >= n) {
			nx -= dx[nd];
			ny -= dy[nd];
			if (nd % 2) nd -= 1;
			else nd += 1;
			cnt++;
		}

		// 블랙홀을 만난 경우
		if (lst[nx][ny] == -1) break;

		// 시작 위치로 돌아온 경우
		if (nx == x && ny == y) break;

		// 웜홀을 만난 경우
		if (lst[nx][ny] >= 6) {
			int wormhole = lst[nx][ny];
			WH wh1 = worm[wormhole][0];
			WH wh2 = worm[wormhole][1];
			if (wh1.x == nx && wh1.y == ny) nx = wh2.x, ny = wh2.y;
			else nx = wh1.x, ny = wh1.y;
		}

		// 블럭을 만난 경우
		if (1 <= lst[nx][ny] && lst[nx][ny] <= 5) {
			nd = blocks[lst[nx][ny]][nd];
			cnt++;
		}
	}
	return cnt;
}

void solution() {
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if (lst[i][j] == 0) {
				for (int k = 0; k < 4; k++) {
					ans = max(ans, sumulation(i, j, k));
				}
			}
		}
	}
}

int main() {
	cin >> tc;
	for (int c = 1; c <= tc; c++) {
		init();
		input();
		solution();
		cout << "#" << c << " " << ans << "\n";
	}
}

 

728x90
반응형