반응형
그래프 탐색이라는 개념이 아직은 낯설어서 응용하기가 어렵다.
이 문제에서는 행렬구조가 입력되는데, 각 boundary를 처리하는데 애를 좀 먹었다.
문제를 풀면서 좌표를 활용할 생각을 못 했는데, 질문 검색을 통해 힌트를 좀 얻었다.
또한, 인터넷 검색을 통해 이 문제에 대한 답을 살펴봤다.
나는 다음 몇가지를 생각해내지 못 해서 이 문제를 푸는데 어려움이 있었다.
- 행렬을 좌표로 표현하기
- 해당 칸까지의 누적거리를 저장하는 배열
아래 코드에서 BFS를 실행하는 while문의 구조는 대략 아래와 같다.
우선, while문은 BFS가 비어있지 않으면 계속 동작한다.
그 이후엔 이미 방문한 칸이 아닐 때까지 pop을 반복한다.
mileage(누적거리)의 값이 -1일 경우 방문하지 않은 경우이다.
만약, BFS가 비어 있으면 반복을 탈출한다.
int x = BFS.front().first;
int y = BFS.front().second;
while (mileage[y * M + x] != -1) {
BFS.pop();
if (BFS.size() == 0)
goto OUT;
x = BFS.front().first;
y = BFS.front().second;
}
해당 칸의 인접한(상하좌우) 칸 중 유효한 위치에 있으면서 방문하지 않은 칸을 큐에 추가한다.
모두 추가했으면 현재 칸을 큐에서 제외시킨다.
for (const auto& adjoin : adjoins)
if (x + adjoin.first >= 0 && x + adjoin.first <= M - 1 && y + adjoin.second >= 0 && y + adjoin.second <= N - 1)
if (maze[(y + adjoin.second) * M + x + adjoin.first])
BFS.push(make_pair(x + adjoin.first, y + adjoin.second));
BFS.pop();
위에서 adjoins는 아래와 같은 pair<int, int>형식으로 정의돼 있다.
pair<int, int> adjoins[4] = { make_pair(0, 1), make_pair(0, -1), make_pair(-1, 0), make_pair(1, 0) };
현재 칸의 위치가 (0, 0)인 경우 mileage의 값을 1로 지정하고 다음 반복을 계속한다.
if (x + y == 0) {
mileage[y * M + x] = 1;
continue;
}
인접 칸들의 mileage 값 중 제일 작은 값에 1을 더한 값을 현재 칸의 mileage 값에 대입한다.
int min_mileage = -1;
for (const auto& adjoin : adjoins)
if (x + adjoin.first >= 0 && x + adjoin.first <= M - 1 && y + adjoin.second >= 0 && y + adjoin.second <= N - 1)
if (mileage[(y + adjoin.second) * M + x + adjoin.first] != -1)
if (min_mileage == -1)
min_mileage = mileage[(y + adjoin.second) * M + x + adjoin.first];
else if (mileage[(y + adjoin.second) * M + x + adjoin.first] < min_mileage)
min_mileage = mileage[(y + adjoin.second) * M + x + adjoin.first];
mileage[y * M + x] = min_mileage + 1;
현재 칸의 위치가 (M - 1, N - 1)인 경우 마지막 칸이므로 반복을 탈출한다.
if (y * M + x == N * M - 1)
break;
전체 코드는 아래와 같다.
#include <cstdio>
#include <queue>
using namespace std;
int main() {
int N, M;
scanf("%d %d", &N, &M);
int* maze = new int[N * M];
for (size_t i = 0; i < N * M; i++) {
char c = getchar();
if (c == '\n')
c = getchar();
maze[i] = c - '0';
}
int* mileage = new int[N * M];
for (size_t i = 0; i < N * M; i++)
mileage[i] = -1;
queue<pair<int, int>> BFS;
BFS.push(make_pair(0, 0));
pair<int, int> adjoins[4] = { make_pair(0, 1), make_pair(0, -1), make_pair(-1, 0), make_pair(1, 0) };
while (BFS.size()) {
int x = BFS.front().first;
int y = BFS.front().second;
while (mileage[y * M + x] != -1) {
BFS.pop();
if (BFS.size() == 0)
goto OUT;
x = BFS.front().first;
y = BFS.front().second;
}
for (const auto& adjoin : adjoins)
if (x + adjoin.first >= 0 && x + adjoin.first <= M - 1 && y + adjoin.second >= 0 && y + adjoin.second <= N - 1)
if (maze[(y + adjoin.second) * M + x + adjoin.first])
BFS.push(make_pair(x + adjoin.first, y + adjoin.second));
BFS.pop();
if (x + y == 0) {
mileage[y * M + x] = 1;
continue;
}
int min_mileage = -1;
for (const auto& adjoin : adjoins)
if (x + adjoin.first >= 0 && x + adjoin.first <= M - 1 && y + adjoin.second >= 0 && y + adjoin.second <= N - 1)
if (mileage[(y + adjoin.second) * M + x + adjoin.first] != -1)
if (min_mileage == -1)
min_mileage = mileage[(y + adjoin.second) * M + x + adjoin.first];
else if (mileage[(y + adjoin.second) * M + x + adjoin.first] < min_mileage)
min_mileage = mileage[(y + adjoin.second) * M + x + adjoin.first];
mileage[y * M + x] = min_mileage + 1;
if (y * M + x == N * M - 1)
break;
}
OUT:
printf("%d\n", mileage[N * M - 1]);
delete[] maze;
delete[] mileage;
return 0;
}
반응형
'프로그래밍 > PS' 카테고리의 다른 글
[C++] 백준 2667번: 단지번호붙이기 (0) | 2020.10.11 |
---|---|
[C++] 백준 7576번: 토마토 (0) | 2020.10.08 |
[C++] 백준 2840번: 행운의 바퀴 (0) | 2020.10.04 |
[C++] 백준 1260번: DFS와 BFS (0) | 2020.10.04 |
[C++] 백준 1463번: 1로 만들기 (0) | 2020.09.30 |