백준 그래프 2206 벽 부수고 이동하기

2020. 3. 17. 03:57Algorithm/문제풀이

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

 

2206번: 벽 부수고 이동하기

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로로 이동하려 한다. 최단경로는 맵에서 가장 적은 개수의 칸을 지나는 경로를 말하는데, 이때 시작하는 칸과 끝나는 칸도 포함해서 센다. 만약에 이동하는 도중에 한 개의 벽을 부수고 이동하는 것이 좀 더 경로가 짧아진다면, 벽을 한 개 까지 부수고 이동

www.acmicpc.net

위 문제는 기존의 그래프 문제들과는 많이 다른 유형이었다. 큐나 배열에 해당 좌표뿐만 아니라 벽을 부술 수 있는지와 이전에 벽을 부술 수 있는지를 체크해야했다. 그래서 아래 코드에는 1이면 벽을 부술 수 있다. 0이면 벽을 부술 수 없다로 코드를 작성하였습니다. 

 

벽을 만난적이 있는지 확인하기 위해 canVisit이라는 변수를 만들어서 확인했습니다.

 

일반적인 길(0)이라면 벽을 만난적이 있는지 없는지에 따라 canVisit으로 확인하여 만나적 있다면 [y][x][0]에 값을 저장하고 있다면 [y][x][1]에 값을 저장합니다. 

 

이전에 벽을 부순적이 있다면 새로운 벽을 만날시에 당연히 부술 수 없습니다. canVisit이 0이면 밑에 map이 1일때 조건문에 들어갈 수 없습니다. 그리고 처음 벽을 부순다고하면 큐에 canVisit에 0 값을 저장하여 이미 벽을 부순 경험이 있다고 저장합니다.  

 

그리고 이전에는 map의 값을 변경하여 방문했던 좌표에 방문을 하지 못하게 만들었는데 아래에서는 map의 값을 변경시킬 수 없어 checked를 통해 방문한적이 있는지 없는지 체크했습니다.

 

부순 경우 및 부술 수 없는 경우 모든 경로를 확인하면 0을 제외한 더 작은 값을 출력하면 됩니다. 

 

더보기
#include <cstdio>
#include <queue>
#include <utility>
#include <algorithm>

using namespace std;

queue <pair<pair<int, int> ,int> > qu;

int map[1002][1002];
int distanceArray[1002][1002][3];
int checked[1002][1002][3]; // 1 벽을 부술 수 있다. 0 벽을 부술 수 없다. 

int xPos[4] = {1, 0, -1, 0};
int yPos[4] = {0, 1, 0, -1};
int destinationCount = 0;

int N, M;

void input();

void bfs();

int main(){
	input();

	bfs();

	if(!distanceArray[N][M][0] && !distanceArray[N][M][1] ){
		printf("-1");
		return 0;
	}

	if(distanceArray[N][M][0] == 0){
		printf("%d", distanceArray[N][M][1]);
	}else if(distanceArray[N][M][1] == 0){
		printf("%d", distanceArray[N][M][0]);
	}else if(distanceArray[N][M][0] < distanceArray[N][M][1]){
		printf("%d", distanceArray[N][M][0]);
	}else{
		printf("%d", distanceArray[N][M][1]);
	}
}

void input(){
	scanf("%d %d", &N, &M);
	for(int y =1; y <= N; y++)
		for(int x = 1; x <= M; x++)
			scanf("%1d", &map[y][x]);

	qu.push(make_pair(make_pair(1, 1), 1));
}


void bfs(){
	distanceArray[1][1][0] = 1;
	distanceArray[1][1][1] = 1;

	checked[1][1][0] = 1;
	checked[1][1][1] = 1;

	while(!qu.empty()){
		pair <int, int> point = qu.front().first;
		int canVisit = qu.front().second;
		qu.pop();

		for(int i = 0; i < 4; i++){
			int ay = point.first+yPos[i]; 
			int ax = point.second+xPos[i];
			if(ay >=1 && ax >=1 && ay <= N && ax <= M){
				if(map[ay][ax] == 0 && checked[ay][ax][canVisit] == 0){
					checked[ay][ax][canVisit] = 1;
					distanceArray[ay][ax][canVisit] = distanceArray[point.first][point.second][canVisit]+1;
					qu.push(make_pair(make_pair(ay,ax), canVisit));
				}else if(map[ay][ax] == 1 && canVisit && checked[ay][ax][0] == 0){
					checked[ay][ax][0] = 1;
					distanceArray[ay][ax][0] = distanceArray[point.first][point.second][canVisit]+1;
					qu.push(make_pair(make_pair(ay,ax), 0));
				}
			
			}	
		}
	}
}

'Algorithm > 문제풀이' 카테고리의 다른 글

백준 10942 팰린드롬?  (0) 2020.03.27
백준 1520 내리막길  (0) 2020.03.27
백준 그래프 1697번 숨박꼭질  (0) 2020.03.17
1629번 곱셈  (0) 2020.02.20
백준 2004 조합 0의 개수  (0) 2020.02.20