-
[백준] 16933 벽 부수고 이동하기 3Problem Solving/Baekjoon Online Judge 2020. 3. 24. 12:57
[문제이해]
1. NxM 으로 표현되는 map이 있다. (0은 이동할 수 있는 공간이고, 1은 이동할 수 없는 벽이다.)
2. 당신은 (1,1)에서 (N,M)위치로 최단 경로로 이동 해야한다.
3. 이 문제에는 낮과 밤이 존재한다. 가장 처음에 이동할 때는 낮이고, 이동할 때마다 낮과 밤이 바뀐다.
4. 이동하지 않고 같은 칸에 머무를 수 있는데, 이때도 낮과 밤이 바뀐다.
3. map에서 벽을 만나면, 벽을 부술 수 있다. (벽은 최대 k개 만큼 부술 수 있다.)
4. 단, 벽은 아침에만 부술 수 있다.
5. map이 주어지고 N, M, k가 주어졌을 때 최단 경로를 구해내야 한다.
[설계]
1. 최단경로를 구하는 문제이므로 BFS를 사용하여 구현한다.
2. BFS로 방문하는 정점의 정보는 4가지이다. (x좌표, y좌표, 벽을 부순 횟수, 낮(0) or 밤(1))
3. Ex1) (0, 0, 0, 0) 은 (0,0)에서 벽을 0번 부쉈고 낮(0)인 상태이다.
4. Ex2) (0, 0, 0, 1) 은 (0,0)에서 벽을 0번 부쉈고 밤(1)인 상태이다.
5. Ex3) (4, 3, 5, 0) 은 (4,3)에서 벽을 5번 부쉈고 낮(0)인 상태이다.
6. 즉, 정점의 상태는 4가지로 표현된다.
7. 따라서 BFS 방문처리 배열은 아래와 같은 4차원 배열을 사용한다.
visited[x좌표][y좌표][벽을 부순 횟수][낮(0) or 밤(1)]
8. 그 외 이동하지 않고 같은 칸에 머무를 수 있는 것, 벽은 아침에만 부술 수 있는 것, 벽은 최대 k개 만큼 부술 수 있는 것, 시작할때는 낮이고 이동할 때마다 낮과 밤이 바뀌는 것 등을 고려하여 BFS를 구현하면된다.
[회고]
- 정점의 상태를 정의하니까 풀기 수월했다.
- 조건이 여러개라 복잡했지만 차근차근 풀어나갔다.
[소스]
#include<iostream> #include<queue> using namespace std; typedef struct { int x, y, broken, day; }pos; int n, m, k; int res = 1e9; int map[1000][1000]; int visited[1000][1000][11][2]; int dx[] = { -1,1,0,0,0 }, dy[] = { 0,0,-1,1,0 }; void bfs() { queue<pos> q; visited[0][0][0][0] = 1; q.push({ 0,0,0,0 }); while (!q.empty()){ int x = q.front().x, y = q.front().y; int broken = q.front().broken, day = q.front().day; int nextDay; if (day == 0) nextDay = 1; else nextDay = 0; q.pop(); if (x == n - 1 && y == m - 1) { res = min(res, visited[x][y][broken][day]); } for (int i = 0; i < 5; i++) { int nx = x + dx[i], ny = y + dy[i]; if (nx >= n || nx < 0 || ny >= m || ny < 0) continue; if(x == nx && y== ny){ if (visited[nx][ny][broken][nextDay] == 0) { visited[nx][ny][broken][nextDay] = visited[nx][ny][broken][day] + 1; q.push({ nx,ny,broken,nextDay }); } } else if (map[nx][ny] == 0 && visited[nx][ny][broken][nextDay] == 0) { visited[nx][ny][broken][nextDay] = visited[x][y][broken][day] + 1; q.push({ nx, ny, broken, nextDay }); } else if (map[nx][ny] == 1 && visited[nx][ny][broken + 1][nextDay] == 0) { if (day == 1) continue; if (broken + 1 > k) continue; visited[nx][ny][broken + 1][nextDay] = visited[x][y][broken][day] + 1; q.push({ nx, ny, broken + 1,nextDay }); } } } } int main() { cin >> n >> m >> k; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { scanf_s("%1d", &map[i][j]); } } bfs(); if (res == 1e9) cout << -1; else cout << res; return 0; }
'Problem Solving > Baekjoon Online Judge' 카테고리의 다른 글
[백준] 1038 감소하는 수 (0) 2020.04.15 [백준] 16234 인구이동 (0) 2020.03.26 [백준] 17141 연구소 2 (0) 2020.03.26 [백준] 16197 두 동전 (0) 2020.03.08 [백준] 13460 구슬 탈출 2 (0) 2020.03.06