일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- git local remote
- 백준 10819
- 백준 1644
- 이진 탐색
- 5582 DP
- android hilt
- 자료구조
- java
- 자바
- 1644 파이썬
- Android Room
- Android mvp
- 1753 다익스트라
- Jetpack Room
- 5582 파이썬
- 1806 백준
- 6588 파이썬
- 1003 파이썬
- 백준 2096
- 안드로이드 hilt
- 2096 파이썬
- Coroutine Flow
- 10819 파이썬
- 1753 파이썬
- flow buffering
- 1806 투포인터
- 1806 파이썬
- 투포인터 알고리즘
- 코루틴 플로우
- 백준 5582
- Today
- Total
Gemstone's Devlog
[백준] 2206번: 벽 부수고 이동하기 본문
https://www.acmicpc.net/problem/2206
2206번: 벽 부수고 이동하기
N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로
www.acmicpc.net
정답률 20프로대의 난이도가 있는 문제였다.
이 문제 역시 BFS 문제였지만, 벽을 한 번 부술 수 있다는 조건이 추가되었기 때문에 생각하기 어려웠던 것 같다.
1. 풀이 방법 및 논리
일반적으로 BFS로 최단거리를 구할 때는 visited[y][x]를 bool 배열로 선언하여 방문여부의 유무를 표현하였다.
그러나 이 문제에서 visited[y][x][power]는 거리 정보를 넣고, 추가로 power이라는 요소를 추가하였는데, 여기서 power는 "y, x 좌표로 오는동안 벽을 부수었는지를 체크하는 값" 을 의미한다. 만약 power가 1이라면 벽을 한 번도 부수지 않았고, 한 번 부술 수 있는 힘이 있다는 뜻이고, 만약 power가 0이라면 이미 벽을 한 번 부수고 왔기 때문에 앞으로는 벽을 부술 수 없다는 의미이다.
시작 시에는 벽을 부수지 않은 상태이고, 부술 수 있는 힘이 남아있기 때문에, BFS 큐에 {{0, 0}, 1} 을 push 해준다.
그 후, BFS를 수행하다가 만약 좌표가 (N - 1, M - 1)에 도달하게 된다면 visited 배열에 저장되어 있는 거리 값을 return 해주면 된다.
만약 큐가 비워질 때까지 마지막 점(N - 1, M - 1)까지 도달하지 못한다면, 이는 해당 좌표까지의 이동이 불가능한 상태이기 때문에 -1을 return 해주는 방식으로 소스코드를 짰다.
2. 소스코드
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <algorithm>
using namespace std;
const int MAX = 1001;
int N, M;
int map[MAX][MAX];
int visited[MAX][MAX][2];
int dy[] = { 0, 0, -1, 1 };
int dx[] = { -1, 1, 0, 0 };
int BFS() {
queue<pair<pair<int, int>, int>> q;
q.push({{0, 0}, 1}); // 큐에 시작 위치 좌표 0,0 과 벽을 부술 수 있다는 의미의 1을 넣어줌
visited[0][0][1] = 1;
while(!q.empty()) {
pair<pair<int, int>, int> p = q.front();
q.pop();
if (p.first.first == N - 1 && p.first.second == M - 1)
return visited[N-1][M-1][p.second];
for (int i = 0; i < 4; i++) {
int ny = p.first.first + dy[i];
int nx = p.first.second + dx[i];
int power = p.second;
if (nx < 0 || ny < 0 || nx >= M || ny >= N || visited[ny][nx][power])
continue;
if (power && map[ny][nx] == 1) {
q.push({{ny, nx}, power - 1});
visited[ny][nx][power-1] = visited[p.first.first][p.first.second][power] + 1;
}
if (map[ny][nx] == 0) {
q.push({{ny, nx}, power});
visited[ny][nx][power] = visited[p.first.first][p.first.second][power] + 1;
}
}
}
return -1;
}
int main() {
string input;
cin >> N >> M;
for (int i = 0; i < N; i++) {
cin >> input;
for (int j = 0; j < M; j++) {
map[i][j] = input[j] - '0';
}
}
cout << BFS() << endl;
}
'Data Structure & Algorithms' 카테고리의 다른 글
[백준] 1525번: 퍼즐 (0) | 2021.08.25 |
---|---|
[백준] 5014번: 스타트링크 (0) | 2021.08.24 |
[백준] 3055번: 탈출 (0) | 2021.08.23 |
[백준] 1715번: 카드 정렬하기 (0) | 2021.08.19 |
[백준] 2696번: 중앙값 구하기 (0) | 2021.08.18 |