문제
N×M크기의 배열로 표현되는 미로가 있다.
1 | 0 | 1 | 1 | 1 | 1 |
---|---|---|---|---|---|
1 | 0 | 1 | 0 | 1 | 0 |
1 | 0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 0 | 1 | 1 |
칼킨 미로에서 1은 이동할 수 있는 칸을 나타내고, 0은 이동할 수 없는 칸을 나타낸다. 이러한 미로가 주어졌을 때, (1, 1)에서 출발하여 (N, M)의 위치로 이동할 때 지나야 하는 최소의 칸 수를 구하는 프로그램을 작성하시오. 한 칸에서 다른 칸으로 이동할 때, 서로 인접한 칸으로만 이동할 수 있다.
위의 예에서는 15칸을 지나야 (N, M)의 위치로 이동할 수 있다. 칸을 셀 때에는 시작 위치와 도착 위치도 포함한다.
입력
첫째 줄에 두 정수 N, M(2 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 M개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.
출력
첫째 줄에 지나야 하는 최소의 칸 수를 출력한다. 항상 도착위치로 이동할 수 있는 경우만 입력으로 주어진다.
예제 입력
1
2
3
4
5
4 6
101111
101010
101011
111011
예제 출력
1
15
풀이
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
72
73
74
75
76
77
78
79
/* Date: 2020-08-26 */
#include <iostream>
#include <queue>
#include <stdio.h>
using namespace std;
typedef struct element{
int x;
int y;
int l;
} element;
int N, M, Rst;
int Map[101][101];
int is_visit[101][101];
queue<element> Q;
element init_element(int x, int y, int l);
int is_visitable(int x, int y);
int main(){
cin >> N >> M;
for(int i = 1; i <= N; i++){
for(int j = 1; j <= M; j++){
scanf("%1d", &Map[i][j]);
}
}
is_visit[1][1] = 1;
Q.push(init_element(1, 1, 1));
while(!Q.empty()){
element e = Q.front();
Q.pop();
if(e.x == N && e.y == M){
Rst = e.l;
break;
}
//Top
if(is_visitable(e.x - 1, e.y)){
is_visit[e.x - 1][e.y] = 1;
element temp = init_element(e.x - 1, e.y, e.l + 1);
Q.push(temp);
}
//Down
if(is_visitable(e.x + 1, e.y)){
is_visit[e.x + 1][e.y] = 1;
element temp = init_element(e.x + 1, e.y, e.l + 1);
Q.push(temp);
}
//Left
if(is_visitable(e.x, e.y - 1)){
is_visit[e.x][e.y - 1] = 1;
element temp = init_element(e.x, e.y - 1, e.l + 1);
Q.push(temp);
}
//Right
if(is_visitable(e.x, e.y + 1)){
is_visit[e.x][e.y + 1] = 1;
element temp = init_element(e.x, e.y + 1, e.l + 1);
Q.push(temp);
}
}
cout << Rst << endl;
}
element init_element(int x, int y, int l){
element temp;
temp.x = x; temp.y = y; temp.l = l;
return temp;
}
int is_visitable(int x, int y){
if(x >= 1 && x <= N && y >= 1 && y <= M && is_visit[x][y] != 1 && Map[x][y] != 0){
return true;
}
return false;
}
### BFS 개념을 공부하기 좋은 문제이다.
Queue에 원소를 넣는 조건을 사전에 잘 구상하면 어렵지 않게 풀 수 있다.
이 문제의 경우 연속된 숫자 문자열을 숫자로 하나씩 받아야 했다. cin
이 아닌 scanf("%1d", &Map[x][y]);
을 사용해서 해결하였다.
연속된 문자열 중 원하는 만큼만 입력을 받아야 할 때 사용할 수 있으니 기억해두는 게 좋을 것 같다.