BFS for Maze
N × M크기의 배열로 표현되는 미로가 있다. 미로에서 0은 이동할 수 있는 칸을 나타내고, 1은 이동할 수 없는 칸을 나타낸다. S는 출발점을 의미하며 T는 도착점을 의미한다.
이러한 미로가 주어졌을때 BFS를 수행하여 출발점에서 도착점으로 이동하는 최단 경로의 칸 수를 구하는 프로그램을 작성하시오. 한 칸에서 다른 칸으로 이동할 때, 서로 인접한 칸으로만 이동할 수 있다. 칸의 수를 셀 때는 S와 T도 포함한다.
Input
첫째 줄에 두 정수 N, M (2 ≤ N, M ≤ 50)이 주어진다.
다음 N개의 줄에는 M개의 문자로 미로가 주어진다. 각각의 문자들은 붙어서 입력으로 주어진다.
Output
첫째 줄에 BFS를 통해 지나야 하는 최단 경로의 칸 수를 출력한다. 도착점에 도달할 수 없는 경우는 0을 출력한다.
Sample Input 1
4 6
1S1000
101010
100010
11100T
Sample Output 1
8
Sample Input 2
4 6
1S1000
101011
100010
11101T
Sample Output 2
0
Sample Input 3
5 6
110S11
100001
101101
100001
111T11
Sample Output 3
7
정답1 (정석 BFS 풀이 이용)
#include <iostream>
#include <queue>
#define MAX 51
using namespace std;
int N, M; // 미로 크기
int maze[MAX][MAX]; // 미로 표현용 2차원 배열
int visited[MAX][MAX]; // 방문 기록용 2차원 배열
int dist[MAX][MAX]; // 이동칸 기록용 2차원 배열
int x_dir[4] = {-1, 1, 0, 0}; // 상화좌우 x축 방향
int y_dir[4] = {0, 0, -1, 1}; // 상화좌우 y축 방향
queue<pair<char,char>> q; // 탐색 좌표 저장용 queue
// 미로 경로 탐색
void bfs(int start_x, int start_y){
visited[start_x][start_y] = 1; // 입력 받은 시작 좌표를 방문
q.push(make_pair(start_x,start_y)); // queue 에 삽입
dist[start_x][start_y]++; // 시작 좌표까지 이동한 칸을 1로 지정
// 모든 좌표를 탐색할 때까지 반복
while (!q.empty()){
// queue 의 front 좌표를, 현재 좌표로 지정
int x = q.front().first;
int y = q.front().second;
// qeueu 의 front 좌표 제거
q.pop();
// 현재 좌표와 상하좌우로 인접한 좌표 확인
for (int i=0; i<4; ++i){
// 현재 좌표와 상하좌우로 인접한 좌표
int x_new = x + x_dir[i];
int y_new = y + y_dir[i];
// 인접한 좌표가, 미로 내에 존재하는지, 방문한 적이 없는지, 이동이 가능한지 확인
if ( (0 <= x_new && x_new < N) && (0 <= y_new && y_new < M)
&& !visited[x_new][y_new] && (maze[x_new][y_new] == '0' || maze[x_new][y_new] == 'T')){
visited[x_new][y_new] = 1; // 인접 좌표는 방문한 것으로 저장
q.push(make_pair(x_new, y_new)); // 인접 좌표를 queue 에 삽입
dist[x_new][y_new] = dist[x][y] + 1; // 인접 좌표까지 이동한 거리 저장
}
}
}
}
int main(){
int aa, bb;
int a,b;
cin >> N >> M; // 미로 크기 입력
for (int i=0; i<N; ++i){ // 미로 입력
string row; // 행 입력
cin >> row;
for (int j=0; j<M; ++j){ // 행 별 좌표값 저장
maze[i][j] = row[j]; // 행 별 좌표값들은 문자 형태이기 때문에, 숫자로 변환
if(maze[i][j]=='S'){
a = i;
b = j;
}
else if(maze[i][j]=='T'){
aa = i;
bb = j;
}
}
}
bfs(a, b); // 미로 탐색 시작
cout << dist[aa][bb] <<endl; // 도착 좌표까지의 거리 출력
}
정답2(직접 클래스 구현):
#include <deque>
#include <stack>
#include <iostream>
using namespace std;
struct Location2D {
int row; //현재위치의 행번호
int col; // 현재위치의 열번호
Location2D(int r = 0, int c = 0) { row = r; col = c; }
bool isNeighbor(Location2D& p) { //위치 p가 자신의 이웃인지 검사하는 함수
return ((row == p.row && (col == p.col - 1 || col == p.col + 1)) || (col == p.col && (row == p.row - 1 || row == p.row + 1)));
}
//위치 p가 자신과 같은 위치인지를 검사하는 함수(연산자 오버로딩 사용)
bool operator ==(Location2D& p) { return row == p.row && col == p.col; }
};
//(r,c)가 갈 수 있는 위치인지를 검사
//(r,c)가 배열 안에 있고, 값이 갈 수 있는 위치 '0'이거나 출구 'T'이어야함
int main() {
deque<Location2D> locDeque; //위치 큐 객체 생성
int N, M, cnt = 1;
char map[50][50];
int count[50][50] = { 0 }; // 좌표의 거리값을 저장하는 수단
cin >> N >> M;
for (int a = 0; a < N; a++) { // 미로 생성 및 입구 객체 생성
for (int b = 0; b < M; b++) {
cin >> map[a][b];
if (map[a][b] == 'S') {
Location2D entry(a, b); // 입구 객체
count[a][b] = cnt;
locDeque.push_back(entry);
}
}
}
while (!locDeque.empty()) { //큐가 비어있지 않는 동안
Location2D here = locDeque.front(); //큐의 front 상단 객체 복사
locDeque.pop_front(); //큐의 상단 객체 삭제;
int r = here.row;
int c = here.col;
if (map[r][c] == 'T') { // 출구를 만났으면 -> 탐색 성공
printf("%d\n",count[r][c]);
return 0;
}
else { //출구가 아니면
if ((r - 1 >= 0 && c >= 0 && r - 1 < N && c < M) && ((map[r - 1][c] == '0' || map[r - 1][c] == 'T')) && (count[r - 1][c] == 0)) {
locDeque.push_back(Location2D(r - 1, c));
count[r-1][c] = count[r][c] + 1;
}
if ((r + 1 >= 0 && c >= 0 && r + 1 < N && c < M) && ((map[r + 1][c] == '0' || map[r + 1][c] == 'T')) && (count[r + 1][c] == 0)) {
locDeque.push_back(Location2D(r + 1, c));
count[r + 1][c] = count[r][c] + 1;
}
if ((r >= 0 && c - 1 >= 0 && r < N && c - 1< M) && ((map[r][c - 1] == '0' || map[r][c - 1] == 'T')) && (count[r][c - 1] == 0)){
locDeque.push_back(Location2D(r, c - 1));
count[r][c-1] = count[r][c] + 1;
}
if ((r >= 0 && c + 1 >= 0 && r < N && c + 1< M) && ((map[r][c + 1] == '0' || map[r][c + 1] == 'T')) && (count[r][c + 1] == 0)) {
locDeque.push_back(Location2D(r, c + 1));
count[r][c+1] = count[r][c] + 1;
}
}
}
printf("0\n");
return 0;
}
'CS+PS > data structure' 카테고리의 다른 글
[Queue/Deque] 큐/덱 - 토이 편집기 Undo Redo (0) | 2023.07.09 |
---|---|
[Queue/Deque] 큐/덱 - 정렬 가능 여부 확인 프로그램 (0) | 2023.07.09 |
[Queue/Deque] 큐/덱 - 미팅 주선 프로그램 (0) | 2023.07.09 |
[Stack] 스택 - STL을 이용한 미로찾기 (0) | 2023.07.04 |
[Stack] 스택 - 수식 계산 프로그램 (0) | 2023.07.04 |