-
백준 2206 (벽 부수고 이동하기) c++백준 문제 2022. 2. 25. 15:39728x90
행렬의 크기 nm이 주어지면 1이면 벽이고 0이면 갈 수 있는 길입니다.
이때 벽을 한번 부수고 통과할 수 있다고 할때 최단거리를 구하는 문제입니다.
최단 거리이므로 BFS로 이용하면 됩니다.
원래 평소대로라면 bool visited[x][y] : arr[x][y]에 해당하는 부분을 방문하면 true로 바꿔주었지만
벽을 부수는 경우도 생각해줘야 하기때문에 방문기록이 총 3차원으로 생각할 수 있습니다.
int dist[x][y][0] : 벽을 하나도 안부수고 arr[x][y]까지 도달할 동안 최단거리
int dist[x][y][1] : 벽을 한번 부수고 arr[x][y]까지 도달할 동안 최단거리
즉 약간 dp처럼 생각해주면 됩니다.
1번째 줄 cnt는 마지막에 최단거리를 저장하기 위한 변수입니다.
2번째 줄 end는 탐색을 완료가능한지 체크하기 위한 변수입니다.
end가 true이면 끝까지 탐색가능하므로 cnt를 출력해주고
end가 false이면 탐색 불가능하므로 -1을 출력해주면 됩니다.
3번째 줄을 보면 bfs 부분의 큐 부분을 tuple로 받아주었습니다.
{x, y, 지금까지 벽을 부순 횟수}
10번째 줄은 탐색이 완료되었으므로 최단거리를 cnt에 저장하는
부분 입니다.
이제 상하좌우로 돌아가면서 벽을 부수고 이동가능한지 그냥 이동하는지 확인해줄것입니다.
먼저 조건이 존재합니다.
1) 당연히 다음에 갈 위치가 0보다 작으면 안되고 n이나 m보다 크거나 같으면 안됩니다.
2) dist[nx][ny][check] 가 값이 들어있으면 이전에 방문했다는 증거이므로 continue를 해야합니다.
3) arr[nx][ny]가 0이고 check가 0이면 dist[nx][ny][0] = dist[x][y][0] +1 입니다.
4) arr[nx][ny]가 0이고 check가 1이면 dist[nx][ny][1] = dist[x][y][1] + 1 입니다.
벽을 한번 부쉈기 때문에 부순 상태에서만 생각해줘야 합니다.
5) arr[nx][ny] = 1 이고 check가 0이면 이전에 벽을 부순적이 없으므로
벽을 부술 수 있습니다.
따라서 dist[nx][ny][1] = dist[x][y][0] + 1 입니다.
전체 코드입니다.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172#include<iostream>#include<algorithm>#include<cstring>#include<vector>#include<string>#include<stack>#include<queue>#include<deque>#include<cmath>#include<map>#include<set>#include<tuple>using namespace std;using ll = long long;using ull = unsigned long long;int on[4] = { 0, 1, 0, -1 };int off[4] = { 1, 0, -1, 0 };int arr[1001][1001];int dist[1001][1001][2];string st;int n, m;int main() {ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);cin >> n >> m;for (int i = 0; i < n; i++) {cin >> st;for (int j = 0; j < m; j++) {arr[i][j] = st[j] - '0';}}int cnt;bool end = false;queue<tuple<int, int, int>>q;q.push({ 0, 0, 0 });dist[0][0][0] = 1;while (!q.empty()) {int x = get<0>(q.front());int y = get<1>(q.front());int check = get<2>(q.front());if (x == n - 1 && y == m - 1) {cnt = dist[x][y][check];end = true;break;}q.pop();for (int i = 0; i < 4; i++) {int nx = x + on[i];int ny = y + off[i];if (dist[nx][ny][check])continue;if (nx >= 0 && ny >= 0 && nx < n && ny < m) {if (!arr[nx][ny] && check ==0) {dist[nx][ny][0] = dist[x][y][0] + 1;q.push({ nx, ny,0 });}else if (arr[nx][ny] == 1 && check == 0) {dist[nx][ny][1] = dist[x][y][0] + 1;q.push({ nx, ny, 1 });}else if (!arr[nx][ny] && check == 1) {dist[nx][ny][1] = dist[x][y][1] + 1;q.push({ nx, ny, 1 });}}}}if (end)cout << cnt;else cout << -1;return 0;}cs '백준 문제' 카테고리의 다른 글
백준 1939 (중량제한) c++ (0) 2022.02.26 백준 1697 (숨바꼭질) c++ (0) 2022.02.25 백준 1012 (유기농 배추) c++ (0) 2022.02.25 백준 12895 (화려한 마을) c++ (0) 2022.02.23 백준 10999 (구간 합 구하기 2) (0) 2022.02.22