벽 부수는 것을 처음에 너무 간단하게만 생각했다가 여러번 틀린 문제입니다.
queue에 넣는 조건을 잘 나누지 않으면 메모리 초과가 나오기 십상이니
명확하게 구분해야만 해결할 수 있는 문제였습니다.
먼저, 현재 좌표의 방문 여부를 벽을 부순적이 있는 경우와 없는 경우로 나눠서 진행해야 합니다.
안그러면 아래 예시와 같은 경우에 -1이 나오게 됩니다.
4 4
0000
0 1 1 1
00 1 1
00 10
한번 방문해서 실패했다고 무조건 visited를 true로 바꿔주면..! 아래처럼 되버려서 실패하고 맙니다.
(0,0)->(0,1)->(1,1)->(2,1)->(3,1) 경로로 이동해서 한번 실패했다면, 해당 경로는 전부 visited = true가 되버립니다. 그러면,
(0,0)->(1,0)->(2,0)->(2,1) 의 경로의 경우 막혀버리게 되고
(0,0)->(1,0)->(2,0)->(3,0)->(3,1)의 경로 또한 막혀버리게 됩니다.
그래서 원치않는 -1 값이 나오게 됩니다..
그래서 두 경우로 나눠보면, 아래와 같습니다.
1. 벽 부순 횟수가 0이면서 해당 좌표에 방문한적이 없는 경우
1-1) 해당 좌표에 벽이 없고 이전까지 벽 부순 횟수도 0 일경우
2. 벽 부순 횟수가 1이면서 해당 좌표에 방문한적이 없는 경우
2-1) 해당 좌표에 벽이 있고 벽 부순 횟수가 0일 경우
2-2) 해당 좌표에 벽이 없고 벽 부순 횟수가 1일 경우
아래는 이를 토대로 작성한 코드입니다.
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
#include <iostream>
#include <queue>
#include <string>
using namespace std;
int map[1000][1000];
bool visited[1000][1000][2] = { false };
int xpos[] = { -1,0,1,0 };
int ypos[] = {0, 1, 0, -1};
class Point{
public:
int x;
int y;
int cnt;
int brk;
Point(int x, int y, int brk, int cnt) {
this->x = x;
this->y = y;
this->cnt = cnt;
this->brk = brk;
}
};
int bfs(int n, int m) {
queue<Point> q;
q.push(Point(0,0,0,1));
visited[0][0][0] = true;
visited[0][0][1] = true;
while (!q.empty()) {
Point cur = q.front();
q.pop();
if (cur.x == n-1 && cur.y == m-1) {
return cur.cnt;
}
for (int i = 0; i < sizeof(xpos) / sizeof(int); i++) {
int nx = cur.x + xpos[i];
int ny = cur.y + ypos[i];
if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
// 벽 부순 횟수가 0이면서 해당 좌표에 방문한적이 없는 경우
if (!visited[nx][ny][0]) {
// 해당 좌표에 벽이 없고 이전까지 벽 부순 횟수도 0 일경우에만 push
if (map[nx][ny] == 0 && cur.brk == 0) {
q.push(Point(nx, ny, 0, cur.cnt + 1));
visited[nx][ny][0] = true;
}
}
// 벽 부순 횟수가 1이면서 해당 좌표에 방문한적이 없는 경우
if (!visited[nx][ny][1]) {
// 해당 좌표에 벽이 있고 벽 부순 횟수가 0일 경우
// or 해당 좌표에 벽이 없고 벽 부순 횟수가 1일 경우
if ((map[nx][ny] == 1 && cur.brk == 0) || (map[nx][ny] == 0 && cur.brk == 1)) {
q.push(Point(nx, ny, 1, cur.cnt + 1));
visited[nx][ny][1] = true;
}
}
}
}
}
return -1;
}
int main() {
int n, m;
cin >> n >> m;
for (int i = 0; i < n; i++) {
string tmp;
cin >> tmp;
for (int j = 0; j < m; j++)
map[i][j] = tmp[j] - '0';
}
cout << bfs(n,m);
return 0;
}
|
cs |
코드에 문제가 있거나 더 나은 방법이 있는 경우엔 댓글 부탁드립니다 :)
'알고리즘 > BOJ' 카테고리의 다른 글
[백준] 12865번 평범한 배낭 (0) | 2020.05.06 |
---|---|
[백준] 9251번 LCS (0) | 2020.05.06 |
[백준] 1707번 이분 그래프 (0) | 2019.09.17 |
[백준] 13460번 구슬 탈출 2 (0) | 2019.09.15 |
[백준] 2583번 영역 구하기 (0) | 2019.09.11 |