-
[BFS]-응용-벽 부수고 이동하기알고리즘 스터디 01/숙제 2023. 4. 5. 17:07
< BFS > - < 골드 3 >
https://www.acmicpc.net/problem/2206
2206번: 벽 부수고 이동하기
N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로
www.acmicpc.net
[ 2206 ] 벽 부수고 이동하기
N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로로 이동하려 한다. 최단경로는 맵에서 가장 적은 개수의 칸을 지나는 경로를 말하는데, 이때 시작하는 칸과 끝나는 칸도 포함해서 센다.
만약에 이동하는 도중에 한 개의 벽을 부수고 이동하는 것이 좀 더 경로가 짧아진다면, 벽을 한 개 까지 부수고 이동하여도 된다.
한 칸에서 이동할 수 있는 칸은 상하좌우로 인접한 칸이다.
맵이 주어졌을 때, 최단 경로를 구해 내는 프로그램을 작성하시오.
:: 입력 ::
첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 1,000)이 주어진다. 다음 N개의 줄에 M개의 숫자로 맵이 주어진다. (1, 1)과 (N, M)은 항상 0이라고 가정하자.
:: 출력 ::
첫째 줄에 최단 거리를 출력한다. 불가능할 때는 -1을 출력한다.
틀렸다 !
답안 코드를 봤는데도 이해가 안 감
다음에 다시 풀어보기
나는 dist 배열을 하나만 두고 썼는데
답안 코드에서는 dist 배열을 두 개 돌림
그렇게 하는 이유는
벽을 부수는 경우와 부수지 않는 경우에
같은 칸에 도달하더라도 그 칸까지의 경로가 달라지기 때문답안 코드
-#include <iostream> #include <algorithm> #include <string> #include <vector> #include <queue> #include <tuple> using namespace std; #define X first #define Y second #define max 1002 int dir_x[] = { 1, 0, -1, 0 }; int dir_y[] = { 0, -1, 0, 1 }; char board[1000][1000]; // dist[][][0] 벽을 하나도 부수지않고 (x,y)까지 오는데에 걸리는 비용을 저장할 배열 // dist[][][1] 벽을 하나만 부수고 (x,y)까지 오는데 걸리는 비용 int dist[1000][1000][2]; int n, m; // x, y 범위 체크 bool OOB(int x, int y) { return x < 0 || x >= n || y < 0 || y >= m; } int bfs() { // 거리 배열을 -1로 채움 for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) dist[i][j][0] = dist[i][j][1] = -1; // 시작점을 1로 설정( 시작칸과 마지막칸 모두 포함하니까 ) dist[0][0][0] = dist[0][0][1] = 1; // bfs queue<tuple<int, int, int>> q; q.push({ 0,0,0 }); while (!q.empty()) { int x, y, broken; // tie : pair, tuple 등으로 묶인 값을 여러 변수에 한번에 받아올 수 있음 tie(x, y, broken) = q.front(); // 아래 세 문장을 합친 것과 같음 // x = get<0>(q.front()); // y = get<1>(q.front()); // broken = get<2>(q.front()); // (x,y)에 도착했다면 값을 출력 if (x == n - 1 && y == m - 1) return dist[x][y][broken]; q.pop(); int nextdist = dist[x][y][broken] + 1; for (int i = 0; i < 4; ++i) { int nx = x + dir_x[i]; int ny = y + dir_y[i]; // 범위를 벗어났는지 체크 if (OOB(nx, ny)) continue; // 방문한 적 없는 길인 경우 // dist 배열에 거리를 표시하고 q에 넣어줌 if (board[nx][ny] == '0' && dist[nx][ny][broken] == -1) { dist[nx][ny][broken] = nextdist; q.push({ nx,ny,broken }); } // (nx, ny)를 부수는 경우 // broken == 0 이면 아직 벽을 부수지 않았으니 dist[][][0] 배열에 값을 저장하다가 // 벽을 부수는 순간부터 dist[][][1] 배열에 값을 저장하면서 진행하게 됨 // 벽이고 방문하지 않은 곳인 경우 if (!broken && board[nx][ny] == '1' && dist[nx][ny][1] == -1) { dist[nx][ny][1] = nextdist; q.push({ nx, ny, 1 }); } } } // (x,y)에 도달하지 못하면 -1 반환 return -1; } int main(void) { ios::sync_with_stdio(0); cin.tie(0); cin >> n >> m; for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) cin >> board[i][j]; cout << bfs(); return 0; }
'알고리즘 스터디 01 > 숙제' 카테고리의 다른 글
[BFS]-응용-빙산 (0) 2023.04.10 [BFS]-응용-텀 프로젝트 (0) 2023.04.07 [BFS]-기본-토마토(3차원) (0) 2023.04.04 [BFS]-기본-적록색약 (0) 2023.02.15 [BFS]-기본-유기농 배추 (0) 2023.02.14