반응형
한시간 붙잡다가, 풀이 방법에 대해 검색을 조금 해보고 풀었다.
풀이의 핵심은 두가지다.
- 입력은 1 based index이고, 배열은 0 based index
- VISIT[1000][1000]을 두 가지로 구분한다.
하나는 지팡이를 사용했을때의 이동에 대한 경로 VISIT[1000][1000][0]
하나는 지팡이를 사용하지 않았을때의 이동에 대한 경로 VISIT[1000][1000][1]
bfs 한 번으로 해결이 가능하다.
지팡이 사용한 상태에서의 움직임과 지팡이 사용하지 않은 상태에서의 움직임으로 나누기 때문이다.
어차피 지팡이 두번 사용해야 할 경우에 마주한다면, 이미 사용한 상태에서는 방문하지 못하게 되고, 사용하지 않은 상태에서의 움직임에서만 갈 수 있게 되기에 최단 경로 계산에 문제가 되지 않는 것이었다.
핵심
- 벽을 부순 적이 없는데, 벽이 아닌 곳을 마주한다면, 이동한다
- 벽을 부순 적이 없는데, 벽을 마주한다면, 벽을 부수고 이동한다
- 벽을 부순 적이 있는데, 벽이 아닌 곳을 마주한다면, 이동한다
VISIT[X][Y][0] 은, 벽을 부순 적이 없는 상태에서 이동하는 과정에서 사용하고
VISIT[X][Y][1] 은, 벽을 부순 적이 있는 상태에서 이동하는 과정에서 사용한다.
#include <iostream>
#include <queue>
#define MIN(a, b) ((a<=b)?a:b)
#define MAX(a, b) ((a>=b)?a:b)
using namespace std;
int MAP[1000][1000];
bool VISIT[1000][1000][2]; // 0 : 지팡이 사용 안한 상태에서의 움직임. 1 : 지팡이 사용한 상태에서의 움직임.
int DEPTH[1000][1000][2];
int N, M;
int Hx, Hy, Ex, Ey;
int mx[4] = {0, 0, 1, -1};
int my[4] = {1, -1, 0, 0};
int bfs(int x, int y) {
queue<pair<int, pair<int, int>>> que; // (지팡이 사용 유무, x, y)
que.push({0, {x, y}});
VISIT[x][y][0] = VISIT[x][y][1] = true;
while(!que.empty()) {
int isUsed = que.front().first;
int x = que.front().second.first;
int y = que.front().second.second;
if(x == Ex && y == Ey)
return DEPTH[x][y][isUsed];
que.pop();
for(int i = 0; i < 4; i++) {
int tx = x + mx[i];
int ty = y + my[i];
if(tx < 0 || tx >= N || ty < 0 || ty >= M)
continue;
if(isUsed == 0) { // 지팡이 사용 안한 상태라면
if(!VISIT[tx][ty][0] && MAP[tx][ty] == 0) { // 가려는 곳이 도로
que.push({0, {tx, ty}});
VISIT[tx][ty][0] = true;
DEPTH[tx][ty][0] = DEPTH[x][y][0] + 1;
}
if(!VISIT[tx][ty][1] && MAP[tx][ty] == 1) { // 가려는 곳이 벽이면, 사용해서 뚫음
que.push({1, {tx, ty}});
VISIT[tx][ty][1] = true;
DEPTH[tx][ty][1] = DEPTH[x][y][0] + 1;
}
} else { // 지팡이 사용한 상태라면
if(!VISIT[tx][ty][1] && MAP[tx][ty] == 0) { // 가려는 곳이 도로여만 가능
que.push({1, {tx, ty}});
VISIT[tx][ty][1] = true;
DEPTH[tx][ty][1] = DEPTH[x][y][1] + 1;
}
}
}
}
return -1;
}
int main() {
cin >> N >> M >> Hx >> Hy >> Ex >> Ey;
Hx--; Hy--; Ex--; Ey--; // 문제에서의 시작점과 내 시작점은 차이가 있음.
for(int i = 0; i < N; i++) {
for(int j = 0; j < M; j++) {
cin >> MAP[i][j];
}
}
cout << bfs(Hx, Hy) << "\n";
}
소요 시간 : 2시간
반응형
'[백준]' 카테고리의 다른 글
[BaekJoon/백준] 5427번 불 (0) | 2022.07.18 |
---|---|
[BaekJoon/백준] 2234번 성곽 (0) | 2022.07.17 |
[BaekJoon/백준] 14925번 목장 건설하기 (0) | 2022.07.15 |
[BaekJoon/백준] 14500번 테트로미노 (0) | 2022.07.14 |
[BaekJoon/백준] 16234번 인구 이동 (0) | 2022.07.13 |