본문 바로가기

문과 코린이의, [C. C++] 기록/C++ 백준 문제풀이

[문과 코린이의 IT 기록장] C++ 백준 문제풀이[그래프 1] - 미로 탐색 (2178)

반응형

[문과 코린이의 IT 기록장] C++ 백준 문제풀이[그래프 1] - 미로 탐색 (2178)

[문과 코린이의 IT 기록장] C++ 백준 문제풀이[그래프 1] - 미로 탐색 (2178)

 


 

 

2178번: 미로 탐색

첫째 줄에 두 정수 N, M(2 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 M개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.

www.acmicpc.net

[ 문제 ]

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;

}
반응형