컴퓨터 공학 기초/알고리즘 (BFS, DFS)
백준 2206 (벽 부수고 이동하기)
JongSeok_12
2020. 8. 26. 23:32
https://www.acmicpc.net/problem/2206
2206번: 벽 부수고 이동하기
N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로��
www.acmicpc.net
해당 문제는 N by M 크기의 격자판이 주어지고 해당 격자판에서 N , M의 위치까지 최단거리를 찾는 문제이다. 이때 이동시 지켜야할 규칙이 존재한다. 규칙은 다음과 같다.
- 맵 밖으로 벗어날 수 없다.
- 맵에는 벽이 존재하며 벽 1개 까지는 뚫고 갈 수 있다.
- 이동 방향은 위, 아래, 좌, 우측으로 이동이 가능하다.
여기서 핵심은 벽을 최대 1개까지 뚫고 가면서 이동할 때 N, M에 도착하는 최단 시간을 구하는 부분이다.
풀이 :
이미 이동한 경로를 체크해줄 visit 배열을 사용하며 이때 visit 배열은 3차원 배열을 사용한다. 3차원 배열을 사용하여 벽을 뚫고 갔을 때 의 경우와 벽을 뚫고 가지 않았을 경우 2가지를 따로 Check 한다.
#include <iostream>
#include <queue>
using namespace std;
// 벽을 뚫은 Node는 wall = 1
// 벽을 뚫은 적 없는 Node는 wall = 0
struct Node{
int y, x;
int wall;
int cnt;
};
int n, m;
int res = 10000000;
int checkY[4] = { 0, 0, +1, -1 };
int checkX[4] = { 1, -1, 0, 0 };
char map[1001][1001];
// visit[dy][dx][0] => 아직 벽을 뚫지 않은 경우
// visit[dy][dx][1] => 벽을 한번 뚫은 경우
int visit[1001][1001][2] = { 0 };
void bfs(){
queue<Node> qu;
qu.push({ 1, 1, 0, 1 });
visit[1][1][0] = 1;
while (!qu.empty()){
Node now = qu.front();
// n m 도착시 현재 cnt 갱신
if (now.y == n && now.x == m){
res = now.cnt;
return;
}
for (int i = 0; i < 4; ++i){
int dy = now.y + checkY[i];
int dx = now.x + checkX[i];
if (dy <= 0 || dx <= 0 || dy > n || dx > m)continue;
// 벽을 뚫지 않았으며 아직 방문한적 없을 경우
if (now.wall == 0 && visit[dy][dx][0] == 0){
// 현재 방문하는 곳이 벽일 경우 wall 을 1로 변경하여 push
// visit[][][1] 째 배열에 벽을 뚫은 경우의 이동 경로를 저장
if (map[dy][dx] == '1'){
visit[dy][dx][1] = 1;
qu.push({ dy, dx, 1, now.cnt + 1 });
}
// 현재 방문하는 곳이 벽이 아닐경우 wall 은 0이며
// visit[][][0] 째 배열에 벽을 뚫지 않은 경우의 이동 경로 저장
if (map[dy][dx] == '0'){
visit[dy][dx][0] = 1;
qu.push({ dy, dx, 0, now.cnt + 1 });
}
}
// 벽을 이미 한번 뚫은 경우
if (now.wall == 1){
// 이동하는 곳이 벽이 아니면서 벽을 뚫은 경우의 이동경로 중 방문한적 없는 경우만 push
if (map[dy][dx] == '0' && visit[dy][dx][1] == 0){
visit[dy][dx][1] = 1;
qu.push({ dy, dx, 1, now.cnt + 1 });
}
}
}
qu.pop();
}
res = -1;
return;
}
int main(){
//freopen_s(new FILE*, "tes.text", "r", stdin);
cin >> n >> m;
for (int i = 1; i <= n; ++i){
for (int j = 1; j <= m; ++j){
cin >> map[i][j];
}
}
bfs();
cout << res << endl;
}