Algorithm

목수의 미로 탈출 (BFS)

DDunTory 2021. 1. 30. 12:27

문제


아래와 같이 이동할 수 있는 길, 그리고 이동할 수 없는 벽으로 이루어진 크기 N x M 의 지도가 주어진다. 이 때, (N-1, 0) 에서 출발하여 (0, M-1) 까지 도착하는 최단거리를 찾으려 한다. 그런데 목수는 도끼 하나를 갖고 있으며, 이 도끼를 이용하여 벽을 깨부술 수 있다. 하지만 이 도끼는 내구성이 그렇게 좋지 않기 때문에, 벽을 최대 1개밖에 깰 수 없다. 목수가 출발점에서 도착점까지 이동하기 위한 최단거리를 출력하는 프로그램을 작성하시오. 물론, 벽은 최대 1개까지 깰 수 있다. 아래 예제의 경우 ‘X’ 로 표시된 벽을 깰 경우 거리 18만에 출발점에서 도착점으로 이동할 수 있다.

 

입력


첫째 줄에 지도의 세로 길이 N과 지도의 가로 길이 M이 주어진다. ( 1 ≤ N, M ≤ 1,000 ) 둘째 줄부터 지도의 정보가 주어진다. 0은 이동할 수 있는 부분, 1은 이동할 수 없는 부분을 나타낸다.

 

출력


목수가 (N-1, 0) 에서 출발하여 (0, M-1) 까지 이동하는 데 필요한 최단거리를 출력한다. 목수는 미로를 항상 탈출할 수 있다고 가정한다.

 

예제 입력

10 10
0 0 0 0 0 0 1 1 0 0
0 1 1 1 0 0 1 0 1 0 
0 1 1 1 0 0 1 0 1 0
0 0 0 0 0 0 0 0 1 0
0 0 1 1 1 1 0 0 1 0
0 0 0 0 0 0 1 1 0 0
0 0 1 1 1 0 1 1 0 0
0 0 1 1 1 0 0 0 0 0 
0 0 0 0 0 1 1 1 0 0
0 0 0 0 0 0 0 1 0 0

예제 출력

18

 

예제 입력

10 10
0 0 0 0 0 0 1 1 0 0
0 1 1 1 0 0 1 1 1 0
0 1 1 1 0 0 1 1 1 0
0 0 0 0 0 0 0 1 1 0
0 0 1 1 1 1 0 1 1 0
0 0 0 0 0 0 1 1 0 0
0 0 1 1 1 0 1 1 0 0
0 0 1 1 1 0 0 1 0 0
0 0 0 0 0 1 1 1 1 1
0 0 0 0 0 0 0 1 0 0

예제 출력

22



풀이)

벽을 한번만 깰 수 있으니
1) 시작점에서 도착지까지 루트
2) 도착지에서 시작점까지 루트

이 두가지를 BFS로 cost1, cost2 이차원배열에 저장합니다.

 

그러면 벽을 한번만 깨거나 벽을 안깨고 도착할 수 있는 최단거리를 계산할 수 있겠죠?!

 

 


#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
#include <utility>

using namespace std;

const int MAX = 1010;
bool visited[MAX][MAX];	//	방문처리
int map[MAX][MAX], c1[MAX][MAX], c2[MAX][MAX];	//	입력배열, cost1, cost2 배열
int dx[4] = { -1,0,0,1 }, dy[4] = { 0,-1,1,0 };	//	상하좌우
int n, m, result;
queue<pair<int, int>> q;
pair<int, int> p;

void BFS(int x, int y, int cost[MAX][MAX])
{
	visited[x][y] = true;
	p.first = x, p.second = y;
	q.push(p);

	while (!q.empty())
	{
		pair<int, int> current = q.front();
		q.pop();

		int nx = current.first, ny = current.second;

		for (int i = 0; i < 4; i++)
		{
			int xx = nx + dx[i], yy = ny + dy[i];
			if (1 <= xx && xx <= n && 1 <= yy & yy <= m && !visited[xx][yy])
			{
				visited[xx][yy] = true;
				cost[xx][yy] = cost[nx][ny] + 1;

				if (!map[xx][yy])
				{
					pair<int, int> temp;
					temp.first = xx, temp.second = yy;
					q.push(temp);
				}
			}
		}
	}
}
int main()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++) cin >> map[i][j];

	BFS(n, 1, c1);
	memset(visited, 0, sizeof(visited));
	BFS(1, m, c2);

	result = MAX*MAX;

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (c1[i][j] > 0 && c2[i][j] > 0)
				result = min(result, c1[i][j] + c2[i][j]);
		}
	}
	
	cout << result;

	return 0;
}