알고리즘 문제풀이/백준

[백준/BOJ] 2206번 벽 부수고 이동하기 (C++)

노력의천재 2021. 10. 29. 15:04

https://www.acmicpc.net/problem/2206

 

2206번: 벽 부수고 이동하기

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로

www.acmicpc.net

벽 뚫기 사용의 유무를 체크하기 위해 3차원 배열을 이용해야 한다. 해당 아이디어만 잘 떠올린다면 어렵지 않게 해결할 수 있는 BFS 문제였다.

 

#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;

int N, M;
int map[1001][1001];
int visit[2][1001][1001];
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};

struct Pos {
	int x, y, flag; // flag - 0 : 벽 뚫기를 아직 사용 안함, 1: 벽 뚫기를 이미 사용함
};

int BFS() {
	queue<Pos> q;
	q.push({ 0, 0, 0 });
	visit[0][0][0] = 0;

	while(!q.empty()) {
		int x = q.front().x;
		int y = q.front().y;
		int flag = q.front().flag;
		q.pop();
		
		if(x == N - 1 && y == M - 1) return visit[flag][x][y] + 1;
		
		for(int i = 0; i < 4; i++) {
			int nx = x + dx[i];
			int ny = y + dy[i];
			if(nx >= 0 && nx < N && ny >= 0 && ny < M) {
                // 탐색하는 칸을 처음 방문하고, 벽이 없을 때
				if(visit[flag][nx][ny] == -1 && map[nx][ny] == 0) {
					q.push({ nx, ny, flag });
					visit[flag][nx][ny] = visit[flag][x][y] + 1;
                // 탐색하는 칸에 벽이 있고, 아직 벽 뚫기를 사용 안했을 때
				} else if(map[nx][ny] == 1 && flag == 0) {
					q.push({ nx, ny, 1 });
					visit[1][nx][ny] = visit[flag][x][y] + 1;
				}
			}
		}
	}
	
	return -1;
}

int main(void) {
	//freopen("input.txt", "rt", stdin);
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	
	cin >> N >> M;
	for(int i = 0; i < N; i++) {
		string str;
		cin >> str;
		for(int j = 0; j < str.size(); j++) {
			map[i][j] = str[j] - '0';
		}
	}

	memset(visit, -1, sizeof(visit));
	cout << BFS();
}