문제
NxM 크기의 배열로 표현되는 미로가 있다.
미로에서 1은 이동할 수 있는 칸, 0은 이동할 수 없는 칸이다.
이때 (1, 1)에서 출발하여 (N, M)으로 이동할 때 지나야 하는 최소의 칸 수를 구하라 한 칸에서 다른 칸으로 이동할 때는 서로 인접한 칸으로만 이동할 수 있다.
칸을 셀 때는 시작 위치와 도착 위치도 포함한다.
입력
첫째 줄에 두 정수 N, M을 입력한다. (2이상 100이하)
이후 정수의 정보를 입력한다.
출력
첫째 줄에 지나야 하는 최소의 칸 수를 출력한다.
접근
출발점에서 도착점까지 최소길이로 가야한다. 그래서 이동할 때마다 카운트를해서 최솟값을 비교하는 방법을 생각해봤지만 BFS로 길을 탐색하다가 한 번 지나간길은 이전에 밟아온 칸에 +1을 해주어 최종적으로 도착점의 수를 출력하면 되겠다라는 생각을 하였다.
정리를 하면 BFS로 길을 탐색하고 현재 위치의 STEP + 1은 다음 위치의 STEP 수가 된다. 따라서 도착점에 저장된 수를 출력하면 된다.
구현
맵의 크기를 입력받고 맵에 대한 정보를 입력받는다. 이때 0과 1이 붙어서 들어오기 때문에 한 칸씩 map에 입력되도록 "%1d"를 사용햇다.
그리고 -1을 해주어 0이 길이되고 -1은 가지못하는 공간으로 표시하였다. 왜냐하면 방문표시를 1부터 할 것이기 때문이다.
cin >> N >> M;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
scanf("%1d", &map[i][j]);
map[i][j] -= 1;
}
}
그 다음 0, 0부터 BFS를 시작한다.
처음에 입력받은 0, 0에 1을 대입한다. 문제에서 출발점과 도착점도 칸 수에 포함시켜야 하기 때문이다.
이후 큐를 통해 BFS를 실행하며 다음 칸의 후보들에는 현재 칸에 저장된 수의 +1만큼 저장하여 방문표시도 하고 현재 위치까지의 거리도 표시하도록 한다.
void BFS(int y, int x) {
map[y][x] = 1;
queue<pair<int, int>> q;
q.push({ y,x });
while (!q.empty()) {
int cy = q.front().first;
int cx = q.front().second;
q.pop();
for (int d = 0; d < 4; d++) {
int ny = cy + dir[d][0];
int nx = cx + dir[d][1];
if (RangeCheck(ny, nx) && map[ny][nx] == 0) {
map[ny][nx] = map[cy][cx] + 1;
q.push({ ny, nx });
}
}
}
}
최종적으로 (N-1, M-1)의 값을 출력하면 해가 된다.
cout << map[N - 1][M - 1] << endl;
전체 코드
#include <iostream>
#include<algorithm>
#include <vector>
#include<queue>
#include<cstring>
using namespace std;
const int dir[4][2] = { {1,0},{0,1},{-1,0},{0,-1} };
int N, M;
int map[100][100];
bool RangeCheck(int y, int x) {
return(y >= 0 && y < N) && (x >= 0 && x < M);
}
void BFS(int y, int x) {
map[y][x] = 1;
queue<pair<int, int>> q;
q.push({ y,x });
while (!q.empty()) {
int cy = q.front().first;
int cx = q.front().second;
q.pop();
for (int d = 0; d < 4; d++) {
int ny = cy + dir[d][0];
int nx = cx + dir[d][1];
if (RangeCheck(ny, nx) && map[ny][nx] == 0) {
map[ny][nx] = map[cy][cx] + 1;
q.push({ ny, nx });
}
}
}
}
int main()
{
cin >> N >> M;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
scanf("%1d", &map[i][j]);
map[i][j] -= 1;
}
}
BFS(0, 0);
cout << map[N - 1][M - 1] << endl;
return 0;
}
/*
출발할 때 각 칸이 출발위치로부터 몇 칸 떨어져있는지 표시하기 (방문표시도 동시에 됨)
결국 끝에는 해가 담겨있음
그럼 BFS로 인접한 칸은 기준 점보다 1칸 증가
*/
'알고리즘 풀이 > 백준' 카테고리의 다른 글
[백준 1158] 요세푸스 문제 cpp-py (0) | 2021.02.13 |
---|---|
[백준 7576] 토마토 cpp-py (0) | 2021.02.11 |
[백준 2468] 안전 영역 (0) | 2021.02.10 |
[백준 4963] 섬의 개수 cpp-py (0) | 2021.02.10 |
[백준 2606] 바이러스 cpp-py (0) | 2021.02.10 |