코드트리 미로 타워 디펜스 C++

2023. 10. 12. 17:51알고리즘

문제는 시뮬레이션 문제이다.

 

1. 

삼성 문제는 몇가지 유형으로 나뉜다.

시뮬레이션 문제 역시 몇가지 유형으로 나뉘는 것 같다.

1. 도형 이동 시키는 문제

2. 회전하는 좌표

3. 단순 빡구현

물론 1, 2번도 단순 구현이 많이 있는 편이다.

 

기출문제를 풀다보니 몇가지 요령이 생겼다.

1. 여러가지 함수로 나누어서 풀 것 

이렇게 모듈화를 시키니 나중에 디버깅하기도 편리하고 재사용이 편리하다

2. 푸는 도중에 계속해서 디버깅 할 것

모듈화해서 풀고 각각의 모듈이 완성될 때마다 디버깅을 하니 나중에 디버깅 할 양도 줄어들고 중간 중간에 문제를 위해 최적화를 할 방안을 생각하기가 쉽다.

 

2. 이 문제는 2번 유형에 해당한다. 

 

내가 풀이한 방식은, 배열에 다음에 이동해야할 방향을 담았다. 

처음에는 (0,0)부터 (n/2, n/2)로 가는 역방향 배열을 만들었는데 문제를 풀어보니 역방향으로는 풀이가 어려워서 정방향으로 풀었다.

 

역방향 코드는 아래와 같다.

 

   while (x != n / 2 || y != n / 2) {
      int ny = y + dy[dir];
      int nx = x + dx[dir];
      if (!inRange(nx, ny) || dirArr[ny][nx] != -1) {
         dir = (dir + 1) % 4;
      }
      dirArr[y][x] = dir;
      y = y + dy[dir];
      x = x + dx[dir];
   }

 

정방향 코드는 아래와 같다.

 

while (1) {
		if (arr[y][x] == 0 || (x==0 && y==0)) {
			break;
		}
		if (arr[y][x] != -1) {
			v.push_back(arr[y][x]);
		}
		dir = dirArr[y][x];
		x = x + dx[dir];
		y = y + dy[dir];
	}
}

그리고 각각 방향을 보며 그 다음에 가야할 좌표를 알 수 있다.

그리고 한번 삭제를 하고 나면 벡터에 가야하는 숫자들을 모두 담아서 문제를 풀었다.

벡터를 사용해서 좌표계에 옮긴다라는 개념을 가지고 풀면 쉽게 풀 수 있는 문제였다.

자세한 설명은 아래에 담았다.

 

 

디버깅의 경우 처음에 있었던 문제는 새로운 배열을 만들었을 때 격자의 범위를 넘는 것이었다. 이는 쉽게 해결했다. 

두번째 문제는 MakeVector의 종료조건이다. 배열인덱스를 넘어서 참고하는 경우, 그리고 배열 인덱스가 0,0까지 모두 차있는 경우 arr[y][x]==0만으로는 탈출 조건이 부족하다. 이를 참고해서 !(x==0 && y==0) 으로 변경했다. 

 

#include <iostream>
#include <vector>
#include <cstring>

using namespace std;

#define MAX_N 26

int n, m, d, p;
int score;

int arr[MAX_N][MAX_N];
int dirArr[MAX_N][MAX_N];

int dx[4] = { 1, 0, -1, 0 }; // 오른쪽 아래 왼쪽 위 
int dy[4] = { 0, 1, 0, -1 };

bool inRange(int x, int y) {
	return x >= 0 && y >= 0 && x < n && y < n;
}

int changeDir(int x) {
	if (x != 0) {
		return x - 1;
	}
	else {
		return 3;
	}
}

void mapDir() {
	int x = n / 2, y = n / 2, dir = 2;
	dirArr[y][x] = dir;
	int count = 1;
	while (1) {
		int iter = count;
		for (int i = 0;i < iter;i++) {
			dirArr[y][x] = dir;
			y = y + dy[dir];
			x = x + dx[dir];
		}
		if (count == n) {
			break;
		}
		dir = changeDir(dir);
		for (int i = 0;i < iter;i++) {
			dirArr[y][x] = dir;
			y = y + dy[dir];
			x = x + dx[dir];
		}
		dir = changeDir(dir);
		count++;
	}
}

void Delete() {
	int x = n / 2, y = n / 2;
	for (int i = 0;i < p;i++) {
		x = x + dx[d];
		y = y + dy[d];
		score += arr[y][x];
		arr[y][x] = -1; // 지운다
	}
}

void MakeVector(vector<int>& v) {
	int x = n / 2, y = n / 2;
	int dir = dirArr[y][x];
	y = y + dy[dir];
	x = x + dx[dir];
	while (1) {
		if (arr[y][x] == 0 || (x==0 && y==0)) {
			break;
		}
		if (arr[y][x] != -1) {
			v.push_back(arr[y][x]);
		}
		dir = dirArr[y][x];
		x = x + dx[dir];
		y = y + dy[dir];
	}
}

void MoveUp(vector<int> v) {
	int x = n / 2, y = n / 2;
	int dir = dirArr[y][x];
	y = y + dy[dir];
	x = x + dx[dir];
	memset(arr, 0, sizeof(arr));
	for (int i = 0;i < v.size() && i < n*n;i++) {
		arr[y][x] = v[i];
		dir = dirArr[y][x];
		x = x + dx[dir];
		y = y + dy[dir];
	}
}

int Erase(vector<int> &v) {
	int should_stop = 0;
	int st = 0, end;
	vector<int> tmp;
	while (st < v.size()) {
		int flag = 0;
		if (st + 3 < v.size()) {
			if (v[st] == v[st + 1] && v[st] == v[st + 2] && v[st] == v[st + 3]) {
				should_stop = 1;
				flag = 1;
			}
			end = st + 3;
			if (flag == 1) {
				while (end < v.size() && v[st] == v[end]) {
					end++;
				}
				for (int i = st;i < end;i++) {
					score += v[i];
				}
				st = end; continue;
			}
		}
		tmp.push_back(v[st]);
		st++;
	}
	v = tmp;
	if (should_stop == 0) {
		return 1;
	}
	else {
		return 0;
	}
}
void MakeMaze(vector<int>& v) {
	int st = 0, end;
	vector<int> tmp;
	while (st != v.size()) {
		end = st + 1;
		while (end < v.size() && v[st] == v[end]) {
			end++;
		}
		int count = end - st;
		tmp.push_back(count);
		tmp.push_back(v[st]);
		st = end;
	}
	v = tmp;
}
void round(void) {
	vector<int> v;
	// 몬스터를 없앤다
	Delete();
	// 없앤 후 남은 몬스터들의 배열을 만든다
	MakeVector(v);
	while (1) { // 벡터를 기반으로 4개 연속한 경우 삭제하고 변화가 없을 때까지 다시 백터 만들기를 반복한다
		if (Erase(v)) break;
	}
	MakeMaze(v);
	MoveUp(v);
//	cout << "hi" << endl;
}

int main(void) {
	cin.tie(NULL);
	ios::sync_with_stdio(false);
	cin >> n >> m;
	for (int i = 0;i < n;i++) {
		for (int j = 0;j < n;j++) {
			cin >> arr[i][j];
		}
	}

	mapDir(); // 방향을 표시한다
	for (int i = 0;i < m;i++) {
		cin >> d >> p;
		round();
	}
	cout << score << endl;
	return 0;
}

 

'알고리즘' 카테고리의 다른 글

프로그래머스 여행경로 C++  (0) 2023.10.19
코드트리 메이즈 러너 C++  (1) 2023.10.14
프로그래머스 의상 C++  (0) 2023.10.01
프로그래머스 전화번호 목록 C++  (0) 2023.10.01
프로그래머스 단어변환 C++  (2) 2023.09.30