룰루랄라 코딩기록장
[Baekjoon] 백준 2178번 미로탐색(지나온 경로탐색 추가) 본문
2178번 미로탐색 문제 풀이
문제
- N×M크기의 배열로 표현되는 미로가 있다.미로에서 1은 이동할 수 있는 칸을 나타내고, 0은 이동할 수 없는 칸을 나타낸다. 이러한 미로가 주어졌을 때, (1, 1)에서 출발하여 (N, M)의 위치로 이동할 때 지나야 하는 최소의 칸 수를 구하는 프로그램을 작성하시오. 한 칸에서 다른 칸으로 이동할 때, 서로 인접한 칸으로만 이동할 수 있다.
위의 예에서는 15칸을 지나야 (N, M)의 위치로 이동할 수 있다. 칸을 셀 때에는 시작 위치와 도착 위치도 포함한다.
입력
- 첫째 줄에 두 정수 N, M(2 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 M개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.
출력
- 첫째 줄에 지나야 하는 최소의 칸 수를 출력한다. 항상 도착위치로 이동할 수 있는 경우만 입력으로 주어진다.
해결방법
- 최단경로를 확인하기 위해서는 DFS보다는 BFS를 주로 사용한다. DFS를 사용하게되면 시작점에서 도착점으로 갈 수 있는 모든 방법을 수행하지만 BFS는 도착점에 도달하면 최단경로를 구하고 종료된다.
- 시작 지점의 가중치를 1로 시작하고, 인접한 위치로 이동 할 때 이전 지점의 가중치+1 을 해주며 최종 목적지의 가중치를 출력해주면 된다.
코드
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstdio>
#pragma warning(disable:4996)
using namespace std;
int maze[101][101];
int group[101][101];
int dx[] = { 0,0,1,-1 };
int dy[] = { 1,-1,0,0 };
int n, m;
void bfs(int x, int y) {
queue<pair<int, int>> q;
q.push(make_pair(x, y));
group[x][y] = 1;
while (!q.empty()) {
int nx = q.front().first;
int ny = q.front().second;
q.pop();
for (int k = 0; k < 4; k++) {
int xn = nx + dx[k];
int xy = ny + dy[k];
if(xn >=0 && xn <n && xy >=0 && xy <m)
if (maze[xn][xy] == 1 && group[xn][xy] == 0) {
q.push(make_pair(xn, xy));
group[xn][xy] = group[nx][ny] + 1;
}
}
}
}
int main() {
cin >> n >> m;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
scanf("%1d", &maze[i][j]);
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (maze[i][j] == 1 && group[i][j] == 0)
bfs(i, j);
}
}
cout << group[n - 1][m - 1] << "\n";
return 0;
}
추가코드
- 실제로 지나온 경로를 출력하는 코드
pair<int, int> p[101][101];
void bfs(int x, int y) {
group[x][y] = 1;
queue<pair<int, int>> q;
q.push(make_pair(x, y));
while (!q.empty()) {
int x = q.front().first;
int y = q.front().second;
q.pop();
for (int k = 0; k < 4; k++) {
int next_x = x + dx[k];
int next_y = y + dy[k];
if (next_x >= 0 && next_x < n && next_y >= 0 && next_y < m) {
if (maze[next_x][next_y] == 1 && group[next_x][next_y] == 0) {
q.push(make_pair(next_x, next_y));
group[next_x][next_y] = group[x][y] + 1;
p[next_x][next_y] = { x,y };
}
}
}
}
}
int main() {
cin >> n >> m;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
scanf("%1d", &maze[i][j]);
}
}
bfs(0, 0);
vector<pair<int, int>> p2;
int curx = n-1, cury = m-1;
while (true) {
p2.push_back(make_pair(curx, cury));
if (curx == 0 && cury == 0) break;
int nx = p[curx][cury].first;
int ny = p[curx][cury].second;
curx = nx;
cury = ny;
}
for (int i = p2.size() - 1; i >= 0; i--) {
printf("(%d, %d)\n", p2[i].first, p2[i].second);
}
}
- 추가내용
- pair형 2차원배열 p를 사용하여 p[다음x좌표][다음y좌표] = {현재x좌표, 현재y좌표}를 저장한다.
- vector p2를 사용하여 최종점에 도착하기 이전 좌표부터 차례대로 p2에 저장시킨다.
- 출발점은 0,0이라서 curx, cury가 모두 0이되면 반복문을 중단한다.
- p[curx][cury]는 이전좌표를 저장하고 있기 때문에 p[curx][cury]의 first, second의 값이 다시 curx, cury값이 된다.
- p2에 저장되어있는 좌표는 최종지점에 도달한 좌표부터 거꾸로 저장되어있기 때문에 출력할 때도 뒤에서부터 탐색해준다.
'Algorithm > 그래프' 카테고리의 다른 글
[Baekjoon] 백준 1697번 숨바꼭질 (0) | 2019.05.16 |
---|---|
[Baekjoon] 백준 7576번 토마토 (0) | 2019.05.16 |
[Baekjoon] 백준 4963번 섬의개수 (0) | 2019.05.14 |
[Baekjoon] 백준 2667번 단지번호붙이기 (0) | 2019.05.08 |
[Baekjoon] 백준 1707번 이분그래프 (0) | 2019.05.08 |
Comments