728x90

문제요약: 어떤 2차원 grid가 주어지고 각 셀은 벽 또는 빈 공간이고, 각 셀을 동서남북으로 이동할 수 있고 한칸을 이동하는데 걸리는 시간은 1입니다. 시작점 left-top에서 도착점 right-bottom까지 이동하는 시간이 문제에서 주어지는 maxTime 이하이면 Yes를 리턴하고 아니면 No를 리턴하는 문제입니다.
요약: 출발지점부터 도착지점까지 너비우선탐색(BFS)를 돌려서 도착지점까지의 최단거리를 구합니다. 그리고 도착지점까지의 최단거리가 문제에서 주어진 maxTime초과이거나 혹은 벽에 막혀서 도착지점까지 도착하지 못하는경우 No를 리턴하고 아닌 경우 다 Yes로 리턴합니다.
*BFS: 시작 정점으로부터 가까운 정점을 먼저 방문하고 멀리 떨어져 있는 정점을 나중에 방문하는 순회 방법이고 큐를 사용한다.
3번 문제
#include <bits/stdc++.h> // 모든 표준 라이브러리 헤더들을 가져오는 전처리문
using namespace std; // std라는 namespace에서 사용하려고 한다. 그냥 암기하면 됨
/*
문제:
어떤 grid(2차원 맵이겠죠)가 주어지고, 각 cell은 '#' 또는 '.'이다. ('#'이면 벽이고, '.'이면 빈 공간이라고 생각하면 됨)
각 cell을 동서남북으로 이동할 수 있고, 한 칸을 이동하는 데 걸리는 시간은 1이다.
이 때, 시작점(left top)에서 도착점(right bottom)까지 이동하는 시간이 (문제에서 주어지는 maxTime) 이하이면 Yes를 리턴하고 아니면 No를 리턴하라.
(주의: 모든 cell을 탐색했는데도, 벽('#')에 막혀서 도착점에 도달하지 못할 수도 있음)
*/
string reachTheEnd(vector<string> grid, int maxTime) {
// 높이 height와 너비 width를 저장한다.
// height는 vector의 크기이고, width는 vector의 첫번째 원소(스트링)의 길이를 의미
int height = grid.size(), width = grid[0].size();
// 탐색 시, 동서남북으로 이동하기 위해 미리 세팅해둔 배열
int dirx[4] = {0, 0, 1, -1};
int diry[4] = {1, -1, 0, 0};
// dist[i][j] 정의: 시작점 (0,0)에서 현재 좌표 (i,j)까지의 최단 거리를 저장
// dist 벡터는 2차원 벡터로서, 원본 맵 grid와 같은 크기(height * width)를 갖는다. (예제 데이터대로면 3*4)
// 높이는 height이고, 너비는 width인데, 모든 원소의 값을 -1로 초기화한다.
// -1의 의미: 아직까지 도달하지 못했음을 의미. 만약 -1이 아니라면 이미 도착했다는 것이다.
vector<vector<int> > dist(height, vector<int>(width, -1));
dist[0][0] = 0; //시작점 (0,0)은 거리가 당연히 0이다. 시작점에서 시작점까지니까
/*
BFS(너비우선탐색)을 위해 큐를 선언하는데, 큐에 들어가는 각 원소는 pair 타입이다. (왜냐면 좌표를 저장해야하므로)
pair는 STL에 내장된 구조체이다.
*/
queue<pair<int, int> > q;
q.push({0, 0}); //큐에다가 좌표(0, 0)을 넣는다. (BFS 탐색의 시작 위치가 (0,0)이라는 의미)
while (!q.empty()) { // 큐가 비어있지않는 동안
pair<int, int> cur = q.front(); // q에서 맨 앞에 있는 놈(좌표)를 꺼내서 cur라는 pair 타입 변수에 대입
q.pop(); // cur에 저장했으니 q에서 맨 앞에 있는 놈을 삭제한다.
for (int i=0; i<4; i++) { // 동서남북 4가지
/*
현재 좌표 (cur.first, cur.second)에다가 (+dirx[i], +diry[i])를 해서 next 좌표를 구한다.
(+0, +1)하면 동쪽
(+0, -1)하면 서쪽
(+1, +0)하면 남쪽
(-1, +0)하면 북쪽
*/
pair<int, int> next = { cur.first + dirx[i], cur.second + diry[i] };
// next 좌표(동서남북 중 하나)가 grid 밖으로 벗어나는 경우는 continue해서 스킵한다.
if (next.first < 0 || next.first >= height || next.second < 0 || next.second >= width) continue;
// next 좌표(동서남북 중 하나)가 원본 맵(grid)에서 벽인 경우('#'으로 표시된 경우) continue해서 스킵한다. (벽이니까 이동할 수 없음)
if (grid[next.first][next.second] == '#') continue;
// dist[next.first][next.second]가 -1이면(즉, 이때까지 한번도 next 좌표에 도달하지 못한 경우에만)
if (dist[next.first][next.second] == -1) {
// next 좌표의 distance 값을 갱신한다. (cur 좌표에서 1칸 움직인 것이므로, dist[cur.first][cur.second] + 1 값을 대입한다.)
dist[next.first][next.second] = dist[cur.first][cur.second] + 1;
// 큐에 next 좌표를 푸시한다.
q.push(next);
}
}
}
/*
도착점의 좌표는 (height-1, width-1)이다. (왜냐하면, 시작점이 (0,0)이기 때문에 도착점은 (height,width)가 아니라 -1씩 해줘야한다. 예를 들어 길이가 4인 배열은 인덱스가 0,1,2,3임)
만약, 도착점의 distance가 -1이면 "No"를 리턴한다. (즉, 모든 cell을 탐색했는데도, 벽('#')에 막혀서 도착점에 도달하지 못한 경우)
또는 distance가 -1은 아니지만 maxTime보다 크다면 "No"를 리턴한다. (즉, 문제에서 주어진 시간 안에 도착하지 못한 경우)
그 외의 경우는 모두 "Yes"
*/
if (dist[height-1][width-1] == -1 || dist[height-1][width-1] > maxTime) return "No";
return "Yes";
}
int main()
{
// 입력하는 부분 생략하고, 바로 변수에 저장
int n = 3; // size of grid[] rows
vector<string> grid = { "..##", "#.##", "#..." }; //각 element의 타입이 string인 1차원 벡터 grid를 선언한다. 크기는 n이다. (n은 row 갯수=높이를 의미)
int maxTime = 5; // maxTime
// reachTheEnd 함수 호출 후 결과값 저장
string answer = reachTheEnd(grid, maxTime);
// 결과값 출력
cout << answer;
return 0; //정상 종료됨을 의미하는 return 0
}
주석 제거용
#include <bits/stdc++.h>
using namespace std;
string reachTheEnd(vector<string> grid, int maxTime) {
int height = grid.size(), width = grid[0].size();
int dirx[4] = {0, 0, 1, -1};
int diry[4] = {1, -1, 0, 0};
vector<vector<int> > dist(height, vector<int>(width, -1));
dist[0][0] = 0;
queue<pair<int, int> > q;
q.push({0, 0});
while (!q.empty()) {
pair<int, int> cur = q.front();
q.pop();
for (int i=0; i<4; i++) {
pair<int, int> next = { cur.first + dirx[i], cur.second + diry[i] };
if (next.first < 0 || next.first >= height || next.second < 0 || next.second >= width) continue;
if (grid[next.first][next.second] == '#') continue;
if (dist[next.first][next.second] == -1) {
dist[next.first][next.second] = dist[cur.first][cur.second] + 1;
q.push(next);
}
}
}
if (dist[height-1][width-1] == -1 || dist[height-1][width-1] > maxTime) return "No";
return "Yes";
}
int main()
{
int n = 3;
vector<string> grid = { "..##", "#.##", "#..." };
int maxTime = 5;
string answer = reachTheEnd(grid, maxTime);
cout << answer;
return 0;
}
'알고리즘' 카테고리의 다른 글
[2021 ICT 하반기] 5번 문제 (0) | 2021.07.16 |
---|---|
[2021 ICT 하반기] 4번 문제 (0) | 2021.07.16 |
[2021 ICT 하반기] 2번 문제 (0) | 2021.07.15 |
[2021 ICT 하반기] 1번 문제 (0) | 2021.07.15 |