미로 타워 디펜스 [2021-하반기 오후 2번 문제]
문제 링크
삼성 코딩테스트 기출 문제: 미로 타워 디펜스 | 코드트리
주요 IT 기업의 코딩테스트 기출 문제를 연습하며 실전 감각을 키우세요. 취업 합격률을 높이는 필수 연습 과정입니다.

문제 설명
n*n으로 이루어진 나선형 미로에 1,2,3의 몬스터가 있음. 중간에는 플레이어가 있음.
1턴 당 다음과 같은 절차들이 실행됨.
- 플레이어가 상하좌우 방향 중 주어진 공격 칸 만큼 몬스터를 공격해서 없앰 → 점수에 추가
- 빈 공간은 뒤 몬스터들이 채움
- 종류가 같은 몬스터가 4번 이상 반복되면 삭제 → 점수에 추가
- 3번을 해결했는데도 또 4번 이상 반복되는 몬스터가 있으면 삭제
- 몬스터들을 각각 (총 개수, 숫자의 크기)로 변환해서 다시 미로속에 집어넣음
해결 방법
몬스터를 문제에서 설명해준 대로 설정함.
void set_new_monster() {
vector<int> new_monster;
for (int i = 0;i < monster.size();i++) {
int cnt = 0;
for (int j = i;j < monster.size();j++) {
if (monster[i] == monster[j]) cnt++;
else break;
}
new_monster.push_back(cnt);
new_monster.push_back(monster[i]);
if (cnt > 1) {
i += cnt - 1;
}
}
if (new_monster.size() > idx_arr.size()) {
new_monster.resize(idx_arr.size());
}
monster = new_monster;
}
중복된 몬스터 삭제몬스터들을 순회하면서, 4번 이상 반복된 몬스터들을 표시함.
bool delete_duplicate() {
bool ret = false;
for (int i = 0;i < monster.size()-1;i++) {
int cnt = 1;
for (int j = i+1;j < monster.size();j++) {
if (monster[i] == monster[j]) cnt++;
else break;
}
if (cnt >= 4) {
ret = true;
score += cnt * monster[i];
for (int j = 0;j < cnt;j++) {
monster[i + j] = -1;
}
i += (cnt-1);
}
}
return ret;
}
표시된 몬스터들을 제거함.
void erase_remove() {
vector<int> new_monster;
for (int i = 0;i < monster.size();i++) {
if (monster[i] != -1) {
new_monster.push_back(monster[i]);
}
}
monster = new_monster;
}
더이상 표시된 몬스터가 없으면 해당 반복문을 탈출.
플레이어 공격attack_arr
배열에 플레이어가 공격한 위치를 표시함.
void player_attack(int d,int p) {
memset(attack_arr, 0, sizeof(attack_arr));
int x, y;
x = n / 2, y = n / 2;
for (int i = 0;i < p;i++) {
x += dx[d], y += dy[d];
attack_arr[x][y] = 1;
}
}
몬스터들을 순회하면서 공격한 위치에 있는 몬스터는 제거함.
void set_monster() {
memset(arr, 0, sizeof(arr));
int a, b;
vector<int> new_monster;
for (int i = 0;i < monster.size();i++) {
a = idx_arr[i].first, b = idx_arr[i].second;
if (attack_arr[a][b] == 0) {
new_monster.push_back(monster[i]);
}
else {
score += monster[i];
}
}
monster = new_monster;
}
나선형 미로 순서를 벡터에 넣기2차원 배열로 계산하기에는 복잡하니, 벡터로 1차원으로 변환해줌.
void init() {
int x, y;
x = n / 2, y = n / 2;
int dtx[4] = { 0,1,0,-1 };
int dty[4] = { -1,0,1,0 };
int move = 1;
int dir = 0;
int cnt = 0;
while (true) {
for (int i = 0;i < move;i++) {
x += dtx[dir], y += dty[dir];
if (arr[x][y] != 0) monster.push_back(arr[x][y]);
idx_arr.push_back({ x,y });
if (x == 0 && y == 0) break;
}
if (x == 0 && y == 0) break;
dir = (dir + 1) % 4;
cnt++;
if (cnt == 2) {
move++;
cnt = 0;
}
}
}
전체 코드
#include <iostream>
#include <vector>
#include <tuple>
#include <cstring>
using namespace std;
int n, m;
int arr[26][26];
vector<pair<int, int>> attack;
vector<pair<int, int>> idx_arr;
vector<int> monster;
int dx[4] = { 0,1,0,-1 };
int dy[4] = { 1,0,-1,0 };
int attack_arr[26][26];
int score = 0;
void input() {
cin >> n >> m;
for (int i = 0;i < n;i++) {
for (int j = 0;j < n;j++) {
cin >> arr[i][j];
}
}
for (int i = 0;i < m;i++) {
int d, p;
cin >> d >> p;
attack.push_back({ d,p });
}
}
void init() {
int x, y;
x = n / 2, y = n / 2;
int dtx[4] = { 0,1,0,-1 };
int dty[4] = { -1,0,1,0 };
int move = 1;
int dir = 0;
int cnt = 0;
while (true) {
for (int i = 0;i < move;i++) {
x += dtx[dir], y += dty[dir];
if (arr[x][y] != 0) monster.push_back(arr[x][y]);
idx_arr.push_back({ x,y });
if (x == 0 && y == 0) break;
}
if (x == 0 && y == 0) break;
dir = (dir + 1) % 4;
cnt++;
if (cnt == 2) {
move++;
cnt = 0;
}
}
}
void player_attack(int d,int p) {
memset(attack_arr, 0, sizeof(attack_arr));
int x, y;
x = n / 2, y = n / 2;
for (int i = 0;i < p;i++) {
x += dx[d], y += dy[d];
attack_arr[x][y] = 1;
}
}
void set_monster() {
memset(arr, 0, sizeof(arr));
int a, b;
vector<int> new_monster;
for (int i = 0;i < monster.size();i++) {
a = idx_arr[i].first, b = idx_arr[i].second;
if (attack_arr[a][b] == 0) {
new_monster.push_back(monster[i]);
}
else {
score += monster[i];
}
}
monster = new_monster;
}
bool delete_duplicate() {
bool ret = false;
for (int i = 0;i < monster.size()-1;i++) {
int cnt = 1;
for (int j = i+1;j < monster.size();j++) {
if (monster[i] == monster[j]) cnt++;
else break;
}
if (cnt >= 4) {
ret = true;
score += cnt * monster[i];
for (int j = 0;j < cnt;j++) {
monster[i + j] = -1;
}
i += (cnt-1);
}
}
return ret;
}
void erase_remove() {
vector<int> new_monster;
for (int i = 0;i < monster.size();i++) {
if (monster[i] != -1) {
new_monster.push_back(monster[i]);
}
}
monster = new_monster;
}
void set_new_monster() {
vector<int> new_monster;
for (int i = 0;i < monster.size();i++) {
int cnt = 0;
for (int j = i;j < monster.size();j++) {
if (monster[i] == monster[j]) cnt++;
else break;
}
new_monster.push_back(cnt);
new_monster.push_back(monster[i]);
if (cnt > 1) {
i += cnt - 1;
}
}
if (new_monster.size() > idx_arr.size()) {
new_monster.resize(idx_arr.size());
}
monster = new_monster;
}
void solve(int idx) {
player_attack(attack[idx].first, attack[idx].second);
set_monster();
while (1) {
if (delete_duplicate() == false) break;
erase_remove();
}
set_new_monster();
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
// freopen("sample_input.txt", "r", stdin);
input();
init();
for (int i = 0;i < m;i++) {
solve(i);
}
cout << score;
}