반응형
[문과 코린이의 IT 기록장] C++ 백준 문제풀이[그래프 1] - 미로 탐색 (2178)
[ 문제 ]
N×M크기의 배열로 표현되는 미로가 있다.
1 | 0 | 1 | 1 | 1 | 1 |
1 | 0 | 1 | 0 | 1 | 0 |
1 | 0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 0 | 1 | 1 |
미로에서 1은 이동할 수 있는 칸을 나타내고, 0은 이동할 수 없는 칸을 나타낸다. 이러한 미로가 주어졌을 때, (1, 1)에서 출발하여 (N, M)의 위치로 이동할 때 지나야 하는 최소의 칸 수를 구하는 프로그램을 작성하시오. 한 칸에서 다른 칸으로 이동할 때, 서로 인접한 칸으로만 이동할 수 있다.
위의 예에서는 15칸을 지나야 (N, M)의 위치로 이동할 수 있다. 칸을 셀 때에는 시작 위치와 도착 위치도 포함한다.
[ 입력 ]
첫째 줄에 두 정수 N, M(2 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 M개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.
[ 출력 ]
첫째 줄에 지나야 하는 최소의 칸 수를 출력한다. 항상 도착위치로 이동할 수 있는 경우만 입력으로 주어진다.
[ 코드 1 ]
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int a[101][101];
bool check[101][101];
int dx[] = { 0,0,-1,1 };
int dy[] = { -1,1,0,0 };
int n, m; // n:세로, m:가로
int ans = 10001; // 정답
void dfs(int x, int y, int cnt) { // x는 세로, y는 가로
if (x < 0 || y < 0 || x >= n || y >= m)
{
return;
}
if (x == n-1 && y == m-1)
{
ans = min(ans, cnt);
return;
}
for (int i = 0; i < 4; i++)
{
int nx = x + dx[i];
int ny = y + dy[i];
if (0 <= nx && nx < n && 0 <= ny && ny < m)
{
if (a[nx][ny] == 1 && check[nx][ny] == false)
{
check[nx][ny] = true;
dfs(nx, ny, cnt+1);
check[nx][ny] = false;
}
}
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
scanf("%d %d", &n, &m);
for (int i = 0; i < n; i++)
{
for (int k = 0; k < m; k++)
{
scanf("%1d", &a[i][k]);
}
}
// 미로찾기는 (0,0)부터 한번만 시행하면 됨.
dfs(0, 0, 1);
printf("%d\n", ans);
return 0;
}
# DFS 알고리즘 특성상, 최단거리를 찾으려면 완전 탐색을 하고 그 중 가장 작은 값을 선택해야 하는데, 경로가 아주 많을 수 있으므로 시간복잡도가 매우 커진다.
# 반면, BFS는 최단거리를 보장하기 때문에, 이러한 문제(최단거리 구하기)들은 BFS로 풀어야 한다.
[ 코드 2 ]
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
int a[101][101]; // 길 여부 표시
int map[101][101]; // 시작점으로부터 거리 표시
bool check[101][101]; // 방문표시
int dx[] = { 0,0,-1,1 };
int dy[] = { -1,1,0,0 };
int n, m; // n:세로, m:가로
void bfs(int x, int y) { // x는 세로, y는 가로
queue<pair<int, int>> q; // 큐 생성
q.push(make_pair(x, y)); // 시작점 넣기
check[x][y] = true; // 방문표시
while (!q.empty())
{
int x = q.front().first;
int y = q.front().second;
q.pop();
for (int i = 0; i < 4; i++)
{
int nx = x + dx[i];
int ny = y + dy[i];
if (0 <= nx && nx < n && 0 <= ny && ny < m)
{
if (a[nx][ny] == 1 && check[nx][ny] == false)
{
check[nx][ny] = true;
map[nx][ny] = map[x][y] + 1;
q.push(make_pair(nx, ny));
}
}
}
}
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 0; i < n; i++)
{
for (int k = 0; k < m; k++)
{
scanf("%1d", &a[i][k]);
}
}
// 미로찾기는 (0,0)부터 한번만 시행하면 됨.
bfs(0, 0);
printf("%d\n", map[n - 1][m - 1] + 1);
return 0;
}
반응형
'문과 코린이의, [C. C++] 기록 > C++ 백준 문제풀이' 카테고리의 다른 글
[문과 코린이의 IT 기록장] C++ 백준 문제풀이[그래프 1] - 나이트의 이동 (7562) (0) | 2021.10.01 |
---|---|
[문과 코린이의 IT 기록장] C++ 백준 문제풀이[그래프 1] - 토마토 (7576) (0) | 2021.10.01 |
[문과 코린이의 IT 기록장] C++ 백준 문제풀이[그래프 1] - 섬의 개수 (4963) (0) | 2021.09.27 |
[문과 코린이의 IT 기록장] C++ 백준 문제풀이[그래프 1] - 단지번호붙이기 (2667) (0) | 2021.09.27 |
[문과 코린이의 IT 기록장] C++ 백준 문제풀이[그래프 1] - 이분 그래프 (1707) (0) | 2021.09.22 |