Link https://www.acmicpc.net/problem/2206
소스결과 16516 KB / 52 ms
출처 Baekjoon
언어 C++ 17
분류 BFS
설명
벽을 한번 부술 수 있는 상태에서 0,0 에서 n,m 으로 갈 수 있는 최단 거리를 출력해주자.
과거에 비슷한 유형의 문제를 푼 적이 있다.
방문 체크를 할 때 벽을 부순 상태에 따라서 사용해야 하는 방문체크 변수가 다르다.
같은 위치에서 벽을 부수고 왔거나 부수지 않고 온 경우에 따라 도착거리가 달라 질 수 있기 때문이다.
그 부분을 분리해서 진행하면 생각보다 간단한 문제가 된다.
알고리즘
1. 가로, 세로 크기와, 맵 정보를 받는다.
2. 현재 위치에서 상,하,좌,우로 이동하는 경우를 판별한다.
2-1. 다음 위치가 맵 범위에 속하는 경우 다음 위치가 벽인지 아닌지 판단한다.
2-2. 벽이 아닌경우 현재까지 벽을 부순 기록이 있다면 벽을 부순 경우의 방문 체크 변수에 방문체크 후 큐에 넣는다.
2-3. 벽을 부순 기록이 없는 경우 해당 방문 체크 변수에 방문 체크를 하고 큐에 넣는다.
2-4. 벽인경우 현재 벽을 부순 기록이 없다면 기록이 있는 것으로 변경하고 방문 체크를 기록한다.
3. 목적지에 도착하는 경우 BFS를 중단하고 결과를 기록한다.
4. 출력
소스코드
#include <iostream>
using namespace std;
const int QMAX = 1000000;
const int BOARD_MAX = 1000;
struct Point {
int dist;
short x, y;
bool wallBroken;
Point() {};
Point(short x, short y, int dist, bool w) : x(x), y(y), dist(dist), wallBroken(w) {};
};
struct Queue
{
int top = 0;
int rear = 0;
Point data[QMAX];
void push(Point p) {
data[top++ % QMAX] = p;
}
Point pop() {
return data[rear++ % QMAX];
}
bool isEmpty() {
return top % QMAX == rear % QMAX;
}
};
bool board[BOARD_MAX][BOARD_MAX];
short posX[4] = { 1, 0, -1, 0 };
short posY[4] = { 0, 1, 0, -1 };
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
int row, col;
int res = -1;
Queue q;
bool visited[BOARD_MAX][BOARD_MAX] = {};
bool wallVisited[BOARD_MAX][BOARD_MAX] = {};
cin >> col >> row;
for (int i = 0; i < col; i++)
{
char line[BOARD_MAX + 1];
cin >> line;
for (int j = 0; j < row; j++)
board[i][j] = line[j] - '0';
}
q.push(Point(0, 0, 1, false));
visited[0][0] = true;
while (!q.isEmpty()) {
Point cur = q.pop();
//cout << cur.dist << " : " << cur.x << " , " << cur.y << " - " << (cur.wallBroken ? "True" : "False") << endl;
if (cur.x == col - 1 && cur.y == row - 1) {
res = cur.dist;
break;
}
for (int i = 0; i < 4; i++) {
short nextX = cur.x + posX[i];
short nextY = cur.y + posY[i];
if (0 <= nextX && nextX < col && 0 <= nextY && nextY < row) {
// Not wall
if (!board[nextX][nextY]) {
if (cur.wallBroken && !wallVisited[nextX][nextY]) {
wallVisited[nextX][nextY] = true;
q.push(Point(nextX, nextY, cur.dist + 1, cur.wallBroken));
}
else if (!cur.wallBroken && !visited[nextX][nextY]) {
visited[nextX][nextY] = true;
q.push(Point(nextX, nextY, cur.dist + 1, cur.wallBroken));
}
}
// Wall
else {
if (!wallVisited[nextX][nextY] && !cur.wallBroken) {
wallVisited[nextX][nextY] = true;
q.push(Point(nextX, nextY, cur.dist + 1, true));
}
}
}
}
}
cout << res;
return 0;
}
'Algorithm > BFS' 카테고리의 다른 글
Baekjoon 6118 숨바꼭질 (0) | 2019.04.21 |
---|---|
Baekjoon 1967 트리의 지름 (0) | 2019.04.21 |
Baekjoon 16236 아기상어 (0) | 2019.04.12 |
Baekjoon 1463 1로 만들기 (0) | 2019.04.01 |
Baekjoon 17070 파이프 옮기기 1 (0) | 2019.03.12 |