728x90

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

 

2206번: 벽 부수고 이동하기

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

www.acmicpc.net

#include <iostream>
#include <tuple>
#include <algorithm>
#include <queue>
#include <vector>
#include <string>
using namespace std;


int main() {
	int n, m;
	cin >> n >> m;
	vector<string> map;
	for (int i = 0; i < n; i++) {
		string s;
		cin >> s;
		map.push_back(s);
	}

	queue<tuple<int, int, int, int>> q;
	q.push(make_tuple(0, 0, 0, 1)); //행, 열, 벽 부쉈는지 아닌지, 현재까지 몇 칸 거쳐왔는지
	vector<vector<vector<bool>>> visited(2, vector<vector<bool>>(n));
	for (int i = 0; i < 2; i++) {
		for(int j = 0; j < n; j++)
			visited[i][j] = vector<bool>(m);
	}
	vector<int> distance;
	while (!q.empty()) {
		tuple<int, int, int, int> cur = q.front();
		q.pop();
		if (!visited[get<2>(cur)][get<0>(cur)][get<1>(cur)]) {
			if(map[get<0>(cur)][get<1>(cur)] == '0')
				visited[get<2>(cur)][get<0>(cur)][get<1>(cur)] = true;
			if (get<0>(cur) == n - 1 && get<1>(cur) == m - 1) {
				distance.push_back(get<3>(cur));
			}
			else {
				if (get<0>(cur) - 1 >= 0 && map[get<0>(cur) - 1][get<1>(cur)] == '0' && !visited[get<2>(cur)][get<0>(cur) - 1][get<1>(cur)]) {
					q.push(make_tuple(get<0>(cur) - 1, get<1>(cur), get<2>(cur), get<3>(cur) + 1));
				}
				if (get<0>(cur) + 1 < n && map[get<0>(cur) + 1][get<1>(cur)] == '0' && !visited[get<2>(cur)][get<0>(cur) + 1][get<1>(cur)]) {
					q.push(make_tuple(get<0>(cur) + 1, get<1>(cur), get<2>(cur), get<3>(cur) + 1));
				}
				if (get<1>(cur) - 1 >= 0 && map[get<0>(cur)][get<1>(cur) - 1] == '0' && !visited[get<2>(cur)][get<0>(cur)][get<1>(cur) - 1]) {
					q.push(make_tuple(get<0>(cur), get<1>(cur) - 1, get<2>(cur), get<3>(cur) + 1));
				}
				if (get<1>(cur) + 1 < m && map[get<0>(cur)][get<1>(cur) + 1] == '0' && !visited[get<2>(cur)][get<0>(cur)][get<1>(cur) + 1]) {
					q.push(make_tuple(get<0>(cur), get<1>(cur) + 1, get<2>(cur), get<3>(cur) + 1));
				}


				if (get<0>(cur) - 1 >= 0 && map[get<0>(cur) - 1][get<1>(cur)] == '1' && get<2>(cur) == 0 && !visited[get<2>(cur)][get<0>(cur) - 1][get<1>(cur)]) {
					q.push(make_tuple(get<0>(cur) - 1, get<1>(cur), get<2>(cur) + 1, get<3>(cur) + 1));
				}
				if (get<0>(cur) + 1 < n && map[get<0>(cur) + 1][get<1>(cur)] == '1' && get<2>(cur) == 0 && !visited[get<2>(cur)][get<0>(cur) + 1][get<1>(cur)]) {
					q.push(make_tuple(get<0>(cur) + 1, get<1>(cur), get<2>(cur) + 1, get<3>(cur) + 1));
				}
				if (get<1>(cur) - 1 >= 0 && map[get<0>(cur)][get<1>(cur) - 1] == '1' && get<2>(cur) == 0 && !visited[get<2>(cur)][get<0>(cur)][get<1>(cur) - 1]) {
					q.push(make_tuple(get<0>(cur), get<1>(cur) - 1, get<2>(cur) + 1, get<3>(cur) + 1));
				}
				if (get<1>(cur) + 1 < m && map[get<0>(cur)][get<1>(cur) + 1] == '1' && get<2>(cur) == 0 && !visited[get<2>(cur)][get<0>(cur)][get<1>(cur) + 1]) {
					q.push(make_tuple(get<0>(cur), get<1>(cur) + 1, get<2>(cur) + 1, get<3>(cur) + 1));
				}
			}
		}
	}
	if (distance.empty()) cout << -1;
	else {
		int minDist = 1000001;
		for (int i = 0; i < distance.size(); i++) {
			if (distance[i] < minDist)
				minDist = distance[i];
		}
		cout << minDist;
	}
	return 0;
}
728x90

'알고리즘 문제' 카테고리의 다른 글

[백준] 1002번 터렛  (0) 2020.03.07
[백준] 5543번 상근날드  (0) 2020.03.07
[백준] 11816번 8진수, 10진수, 16진수  (0) 2020.03.03
[백준] 2752번 세수정렬  (0) 2020.03.03
[백준] 3896번 소수 사이 수열  (0) 2020.03.03

+ Recent posts