[알고리즘][C] 마법의 숲 탐색
2024. 10. 2. 16:32ㆍ알고리즘 풀이
#include <stdio.h>
#include <string.h>
#define MAX_MAP_SIZE 70
int _R;
int _C;
int _time = 1;
int _dr[4] = {-1, 0, 1, 0};
int _dc[4] = {0, 1, 0, -1};
typedef struct Pos {
int r;
int c;
} Pos;
typedef struct Golem {
Pos center;
int exit_dir;
} Golem;
Pos try_down(int map[][MAX_MAP_SIZE], Golem golem) {
// 밑으로 갈 수 있다면 움직이고 위치 반환 아니면 NULL 반환
for (int i = 1; i < 4; i++) {
Pos cur_pos;
cur_pos.r = golem.center.r + _dr[i];
cur_pos.c = golem.center.c + _dc[i];
cur_pos.r++;
if (cur_pos.r >= _R || (cur_pos.r >= 0 && map[cur_pos.r][cur_pos.c] != 0)) {
return (Pos) {-3, -3};
}
}
Pos ret_pos;
ret_pos.r = golem.center.r + 1;
ret_pos.c = golem.center.c;
return ret_pos;
}
Pos try_left(int map[][MAX_MAP_SIZE], Golem golem) {
// 왼쪽으로 갈 수 있다면 움직이고 위치 반환 아니면 NULL 반환
for (int i = 0; i < 4; i++) {
if (i == 1) {
continue;
}
Pos cur_pos;
cur_pos.r = golem.center.r + _dr[i];
cur_pos.c = golem.center.c + _dc[i];
cur_pos.c--;
if (cur_pos.c < 0 || (cur_pos.r >= 0 && map[cur_pos.r][cur_pos.c] != 0)) {
return (Pos) {-3, -3};
}
}
golem.center.c--;
if (try_down(map, golem).r == -3) {
return (Pos) {-3, -3};
}
Pos ret_pos;
ret_pos.r = golem.center.r + 1;
ret_pos.c = golem.center.c;
return ret_pos;
}
Pos try_right(int map[][MAX_MAP_SIZE], Golem golem) {
// 밑으로 갈 수 있다면 움직이고 위치 반환 아니면 NULL 반환
for (int i = 0; i < 3; i++) {
Pos cur_pos;
cur_pos.r = golem.center.r + _dr[i];
cur_pos.c = golem.center.c + _dc[i];
cur_pos.c++;
if (cur_pos.c >= _C || (cur_pos.r >= 0 && map[cur_pos.r][cur_pos.c] != 0)) {
return (Pos) {-3, -3};
}
}
golem.center.c++;
if (try_down(map, golem).r == -3) {
return (Pos) {-3, -3};
}
Pos ret_pos;
ret_pos.r = golem.center.r + 1;
ret_pos.c = golem.center.c;
return ret_pos;
}
void print(int map[][MAX_MAP_SIZE]) {
for (int i = 0; i < _R; i++) {
for (int j = 0; j < _C; j++) {
printf("%d ", map[i][j]);
}
printf("\n");
}
}
Pos move_golem(int map[][MAX_MAP_SIZE], int start_c, int start_dir) {
Golem golem;
golem.center = (Pos) {-2, start_c};
golem.exit_dir = start_dir;
while (1) {
Pos temp_center;
if ((temp_center = try_down(map, golem)).r != -3) {
golem.center = temp_center;
continue;
}
if ((temp_center = try_left(map, golem)).r != -3) {
golem.center = temp_center;
golem.exit_dir = (3 + golem.exit_dir) % 4;
continue;
}
if ((temp_center = try_right(map, golem)).r != -3) {
golem.center = temp_center;
golem.exit_dir = (1 + golem.exit_dir) % 4;
continue;
}
break;
}
if (golem.center.r <= 0) {
return golem.center;
}
map[golem.center.r][golem.center.c] = _time;
for (int i = 0; i < 4; i++) {
int nr = golem.center.r + _dr[i];
int nc = golem.center.c + _dc[i];
if (i == golem.exit_dir) {
map[nr][nc] = -_time;
}
else {
map[nr][nc] = _time;
}
}
// print(map);
_time++;
return golem.center;
}
Pos move_elf(int map[][MAX_MAP_SIZE], Pos elf_pos) {
int visited[MAX_MAP_SIZE][MAX_MAP_SIZE];
memset(visited, 0, sizeof(visited));
// BFS하며 가장 큰 행이라면 갱신
int max_pos = elf_pos.r + 1;
Pos queue[4900];
int start = 0;
int end = 0;
queue[end++] = elf_pos;
visited[elf_pos.r][elf_pos.c] = 1;
while (start < end) {
Pos cur_pos = queue[start++];
for (int i = 0; i < 4; i++) {
int next_r = cur_pos.r + _dr[i];
int next_c = cur_pos.c + _dc[i];
if (!(0 <= next_r && next_r < _R && 0 <= next_c && next_c < _C)) {
continue;
}
if (visited[next_r][next_c] == 1) {
continue;
}
if (map[next_r][next_c] == 0) {
continue;
}
if (map[cur_pos.r][cur_pos.c] == map[next_r][next_c] || map[next_r][next_c] == -map[cur_pos.r][cur_pos.c] || map[cur_pos.r][cur_pos.c] < 0) {
visited[next_r][next_c] = 1;
Pos next_pos = {next_r, next_c};
queue[end++] = next_pos;
if (max_pos < next_pos.r + 1) {
max_pos = next_pos.r + 1;
}
}
}
}
Pos ret_pos;
ret_pos.r = max_pos;
return ret_pos;
}
int check_valid(Pos elf_pos) {
if (elf_pos.r <= 0) {
return 0;
}
return 1;
}
void reset_map(int map[][MAX_MAP_SIZE]) {
for (int i = 0; i < _R; i++) {
for (int j = 0; j < _C; j++) {
map[i][j] = 0;
}
}
}
int find_elf_loc(int map[][MAX_MAP_SIZE], int start_loc, int start_dir) {
Pos elf_pos = move_golem(map, start_loc, start_dir);
// printf("elf_pos %d %d\n", elf_pos.r, elf_pos.c) ;
if (!check_valid(elf_pos)) {
reset_map(map);
return 0;
}
Pos moved_elf_pos = move_elf(map, elf_pos);
return moved_elf_pos.r;
}
int main() {
int K;
int result = 0;
int map[MAX_MAP_SIZE][MAX_MAP_SIZE];
scanf("%d %d %d", &_R, &_C, &K);
reset_map(map);
for (int i = 0; i < K; i++) {
int start_c;
int start_dir; // 0, 1, 2, 3 : 북, 동, 남, 서
scanf("%d %d", &start_c, &start_dir);
start_c--;
int temp = find_elf_loc(map, start_c, start_dir);
// printf("%d\n", temp);
result += temp;
}
printf("%d\n", result);
}
나의 풀이
- _R과 _C을 이용하는 reset_map을 먼저 돌리고 _R, _C을 받았다. 그러니까 제대로된 결과가 나오지 않을 수밖에
- 또한 try_left, try_right 등에서 밑으로 가니까 golem.center.r + 1을 해야하는데 - 1을 했다.
- 밑의 golem.center.r 이걸로 아래로 갈때 런타임 안되게 막아줘야 하는데 몰랐고 틀린 이후 추가했다.
if (golem.center.r <= 0) {
return golem.center;
}
- 인풋으로 들어오는 변수는 웬만해서는 글로벌 변수로 쓰는것이 합리적이다.
'알고리즘 풀이' 카테고리의 다른 글
[알고리즘] C 코드트리 투어 (2) | 2024.09.26 |
---|---|
[알고리즘] 2개의 사탕 (0) | 2024.08.26 |
[알고리즘] 무한 수열 (0) | 2024.07.30 |
[알고리즘] 스카이라인 (0) | 2024.02.17 |
[알고리즘] 꼬마 정민 (0) | 2024.01.17 |