문제 설명
개발자를 희망하는 죠르디가 카카오에 면접을 보러 왔습니다.
코로나 바이러스 감염 예방을 위해 응시자들은 거리를 둬서 대기를 해야하는데 개발 직군 면접인 만큼
아래와 같은 규칙으로 대기실에 거리를 두고 앉도록 안내하고 있습니다.
- 대기실은 5개이며, 각 대기실은 5x5 크기입니다.
- 거리두기를 위하여 응시자들 끼리는 맨해튼 거리1가 2 이하로 앉지 말아 주세요.
- 단 응시자가 앉아있는 자리 사이가 파티션으로 막혀 있을 경우에는 허용합니다.
예를 들어,
5개의 대기실을 본 죠르디는 각 대기실에서 응시자들이 거리두기를 잘 기키고 있는지 알고 싶어졌습니다. 자리에 앉아있는 응시자들의 정보와 대기실 구조를 대기실별로 담은 2차원 문자열 배열 places가 매개변수로 주어집니다. 각 대기실별로 거리두기를 지키고 있으면 1을, 한 명이라도 지키지 않고 있으면 0을 배열에 담아 return 하도록 solution 함수를 완성해 주세요.
제한 사항
- places의 행 길이(대기실 개수) = 5
- places의 각 행은 하나의 대기실 구조를 나타냅니다.
- places의 열 길이(대기실 세로 길이) = 5
- places의 원소는 P,O,X로 이루어진 문자열입니다.
- places 원소의 길이(대기실 가로 길이) = 5
- P는 응시자가 앉아있는 자리를 의미합니다.
- O는 빈 테이블을 의미합니다.
- X는 파티션을 의미합니다.
- 입력으로 주어지는 5개 대기실의 크기는 모두 5x5 입니다.
- return 값 형식
- 1차원 정수 배열에 5개의 원소를 담아서 return 합니다.
- places에 담겨 있는 5개 대기실의 순서대로, 거리두기 준수 여부를 차례대로 배열에 담습니다.
- 각 대기실 별로 모든 응시자가 거리두기를 지키고 있으면 1을, 한 명이라도 지키지 않고 있으면 0을 담습니다.
풀이
BFS를 이용하여 문제를 풀었지만 데이터의 크기가 작고 조건판단이 번거롭기 때문에 DFS가 더 쉬울 거라는 생각을 한다.
접근법은 간단하다.
5x5배열에서 P를 찾아 맨해튼 거리로 2칸 이내에 P가 있는지 판단하면 된다.
단, 그 사이에 X가 있다면 거리두기를 잘 지키고 있는 것이다.
하지만, O가 있다면 한 번 더 판단해봐야 한다.
즉, queue에 다시 넣어 BFS를 진행해야 한다.
BFS를 진행할 때 보통의 경우 중복으로 방문하는 경우를 제거하기 위해 queue에 넣을 인덱스의 방문여부를 체크한다.
하지만, 이 문제에서 그렇게 하면 다음과 같은 경우에 문제가 생긴다.
P | X |
O | P |
만약 방문 순서가 →, ↓, ←, ↑이었다면 →으로 방문한 뒤 아래에 있는 P에 대해 거리두기가 잘 지켜졌다고 판단하고 방문 여부를 true로 만들어 버린다.
그다음, ↓방향으로 진행된 후, 오른쪽에 있는 P에 대해 이미 처리했다 판단하여 체크하지 않고 넘어간다.
하지만, ↓방향으로는 O를 지나 P가 등장하기 때문에 거리두기가 지켜지지 않은 것이다.
따라서, 이 부분을 처리하기 위해 현재 인덱스에 대해서만 방문 여부를 체크해야 한다.
전체 코드
#include <string>
#include <vector>
#include <queue>
#include <iostream>
using namespace std;
vector<int> dy = {0, 1, 0, -1};
vector<int> dx = {1, 0, -1, 0};
bool Bfs(vector<string>& place, int y, int x)
{
queue<pair<int,int>> q;
vector<vector<bool>> visited(5, vector<bool>(5, false));
q.push({y, x});
int depth = 0;
while(!q.empty() && depth < 2)
{
int size = q.size();
for(int t = 0; t < size; t++)
{
auto [current_y, current_x] = q.front();
q.pop();
visited[current_y][current_x] = true;
for(int i = 0; i < 4; i++)
{
int new_y = current_y + dy[i];
int new_x = current_x + dx[i];
if(new_y < 0 || new_y >= 5 || new_x < 0 || new_x >= 5) continue;
if(visited[new_y][new_x]) continue;
if(place[new_y][new_x] == 'P') return false;
if(place[new_y][new_x] == 'O') q.push({new_y, new_x});
}
}
depth++;
}
return true;
}
vector<int> solution(vector<vector<string>> places) {
vector<int> answer;
for(auto place : places)
{
bool flag = true;
for(int i = 0; i < 5; i++)
{
for(int j = 0; j < 5; j++)
{
if(place[i][j] == 'P')
{
if(!Bfs(place, i, j))
{
answer.push_back(0);
flag = false;
break;
}
}
}
if(!flag) break;
}
if(flag) answer.push_back(1);
}
return answer;
}