[프로그래머스 C++] 미로 탈출
[프로그래머스 C++] 미로 탈출
https://school.programmers.co.kr/learn/courses/30/lessons/159993
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
해결 전략
너비우선탐색 BFS
레버(L)를 먼저 찾은 후에 탈출구(E)를 찾아야 한다.
- 레버(L)를 찾는 BFS 수행
- 주의할 점: 이 때 탈출구를 지나칠 수 있다. 탈출구를 지나도 밖에 나가 끝나지 않고 그냥 지나친 시간만 카운팅한다.
- 방문 체크 초기화
- fill(ch.begin(), ch.end(), vector<int>(c, 0));
- 탈출구(E)를 찾는 BFS 수행
- 주의할 점: 이 때 시작점(S)을 지나칠 수 있다. 이 경우에 수도 체크해야 한다.
※ 참고사항: 2차원 배열의 fill 초기화
fill(ch.begin(), ch.end(), vector<int>(c, 0));
정답 코드
#include <iostream> #include <string> #include <vector> #include <queue> using namespace std; int dirY[4] = { -1, 0, 1, 0 }; int dirX[4] = { 0, -1, 0, 1 }; int answer = -1; // 미로를 빠져나가는데 걸리는 최소 시간. 초기값은 -1로 설정 int solution(vector<string> maps) { int r = maps.size(); int c = maps[0].size(); queue<pair<int, int>> Q; // 레버를 찾을때까지 탐색할 좌표를 저장할 큐 queue<pair<int, int>> secondQ; // 레버를 작동시킨 후 탐색할 좌표를 저장할 큐 vector<vector<int>> ch(r, vector<int>(c, 0)); // 방문한 좌표를 체크할 2차원 벡터 for (int y = 0; y < r; y++) { for (int x = 0; x < c; x++) { if (maps[y][x] == 'S') { // 시작 지점의 좌표를 큐에 넣음 Q.push({ y, x }); } } } int cnt = 0; // 레버를 작동시킨 후의 이동 시간을 저장할 변수 bool bLever = false; // 레버를 작동시켰는지 여부를 저장할 변수 while (!Q.empty()){ int y = Q.front().first; int x = Q.front().second; Q.pop(); for (int i = 0; i < 4; i++) { int ny = y + dirY[i]; int nx = x + dirX[i]; if (ny < 0 || r <= ny || nx < 0 || c <= nx || maps[ny][nx] == 'X') continue; if (maps[ny][nx] == 'O' && ch[ny][nx] == 0){ // 빈 칸('O')이고 방문하지 않았다면 Q.push({ ny, nx }); // 큐에 좌표를 넣고 ch[ny][nx] = ch[y][x] + 1; // 이동 시간를 증가 } else if (maps[ny][nx] == 'E' && ch[ny][nx] == 0) { // 출구('E')이고 방문하지 않았다면 Q.push({ ny, nx }); ch[ny][nx] = ch[y][x] + 1; } else if (maps[ny][nx] == 'L' && ch[ny][nx] == 0) { // 레버('L')이고 방문하지 않았다면 secondQ.push({ ny, nx }); // 레버 작동 후의 좌표를 저장할 큐에 좌표를 넣고 ch[ny][nx] = ch[y][x] + 1; cnt = ch[ny][nx]; // 레버를 작동시킨 좌표의 이동 시간을 저장 //cout << "cnt = " << cnt << "\n"; bLever = true; // 레버 작동 표시 break; } } if (bLever) break; } if (bLever == false) return answer; // 레버를 찾지 못하면 -1을 반환 fill(ch.begin(), ch.end(), vector<int>(c, 0)); // 방문 체크 벡터를 초기화 ch[secondQ.front().first][secondQ.front().second] = cnt; // 레버를 작동시킨 좌표의 이동 시간을 저장 bool bArrived = false; // 종료 지점에 도착했는지 여부를 저장할 변수 while (!secondQ.empty()) { // 레버를 작동시킨 후의 탐색 int y = secondQ.front().first; int x = secondQ.front().second; secondQ.pop(); for (int i = 0; i < 4; i++) { int ny = y + dirY[i]; int nx = x + dirX[i]; if (ny < 0 || r <= ny || nx < 0 || c <= nx || maps[ny][nx] == 'X') continue; if (maps[ny][nx] == 'O' && ch[ny][nx] == 0) { // 빈 칸('O')이고 방문하지 않았다면 secondQ.push({ ny, nx }); ch[ny][nx] = ch[y][x] + 1; } else if (maps[ny][nx] == 'S' && ch[ny][nx] == 0) { // 시작 지점('S')이고 방문하지 않았다면 secondQ.push({ ny, nx }); ch[ny][nx] = ch[y][x] + 1; } else if (maps[ny][nx] == 'E' && ch[ny][nx] == 0) { // 출구('E')이고 방문하지 않았다면 secondQ.push({ ny, nx }); ch[ny][nx] = ch[y][x] + 1; answer = ch[ny][nx]; // 최종 이동 시간을 answer에 저장 bArrived = true; // 도착 표시 break; } } if (bArrived) break; } return answer; } int main() { vector<string> testcase1 = { "SOOOL","XXXXO","OOOOO","OXXXX","OOOOE" }; //vector<string> testcase2 = { "LOOXS","OOOOX","OOOOO","OOOOO","EOOOO" }; cout << solution(testcase1) << "\n"; //cout << solution(testcase2) << "\n"; return 0; }
'⭐ 코딩테스트 > 프로그래머스' 카테고리의 다른 글
[프로그래머스 C++] 리코쳇 로봇 (1) | 2024.02.09 |
---|---|
[프로그래머스 C++] 유사 칸토어 (1) | 2024.02.08 |
[프로그래머스 C++] 테이블 해시 함수 (0) | 2024.02.02 |
[프로그래머스 C++] 거리두기 확인하기 (0) | 2024.02.01 |
[프로그래머스 C++] 가장 큰 정사각형 찾기 (0) | 2023.12.27 |
댓글
이 글 공유하기
다른 글
-
[프로그래머스 C++] 리코쳇 로봇
[프로그래머스 C++] 리코쳇 로봇
2024.02.09 -
[프로그래머스 C++] 유사 칸토어
[프로그래머스 C++] 유사 칸토어
2024.02.08 -
[프로그래머스 C++] 테이블 해시 함수
[프로그래머스 C++] 테이블 해시 함수
2024.02.02 -
[프로그래머스 C++] 거리두기 확인하기
[프로그래머스 C++] 거리두기 확인하기
2024.02.01
댓글을 사용할 수 없습니다.