문제 출처
1. 문제설명
- 대기실은 5개이며, 각 대기실은 5x5 크기입니다.
- 거리두기를 위하여 응시자들 끼리는 맨해튼 거리가 2 이하로 앉지 말아 주세요.
- 맨해튼 거리는 쉽게 말해 모눈종이의 칸 수 이다.
- 단 응시자가 앉아있는 자리 사이가 파티션으로 막혀 있을 경우에는 허용합니다.
2. 입/출력
places
의 5개 행의 각 행은 하나의 대기실 구조
places
의 열 길이(대기실 세로 길이) = 5
P,O,X
로 이루어진 문자열
- P : 응시자가 앉아있는 자리
- O : 빈 테이블
- X : 파티션
- 각 대기실 별로 모든 응시자가 거리두기를 지키고 있으면 1을, 한 명이라도 지키지 않고 있으면 0을 담아 리턴
3. 문제 분류
4. 알고리즘 설계
5x5
크기이므로, 하나씩 탐색하면서 P
라면 BFS를 수행하면 된다.
- 만약 결과가 true이면 맨해튼 거리 2 이하에 앉아있는 다른 사람이 있다는 의미
- BFS
- 현재 위치
x, y
와 거리 정보를 담은 구조체를 큐를 통해 관리하였다.
- 만약 현재 큐에서 꺼낸 거리가 2라면 건너뛴다.
- 그렇지 않다면 4방향 탐색을 진행한다.
- 다음 이동 칸의 값이
O
라면 거리를 1 증가시켜 큐에 담는다.
- 다음 칸이
P
라면 위에 2라면 건너뛴다의 전이므로 false
를 리턴한다.
- 큐가 비어있을 때까지
false
를 리턴하지 않았다면 거리두기를 지키고 있는 것이다.
5. 전체 코드
#include <bits/stdc++.h>
using namespace std;
struct pos {int x, y, d;};
const int dx[] = {-1,1,0,0};
const int dy[] = {0,0,-1,1};
vector<string> board;
bool bfs(int x, int y) {
bool vis[5][5] = {false,};
queue<pos> q;
q.push({x, y, 0});
vis[x][y] = true;
while(!q.empty()) {
pos cur = q.front();
q.pop();
if(cur.d == 2) continue;
for(int dir=0; dir<4; dir++) {
int nx = cur.x + dx[dir];
int ny = cur.y + dy[dir];
if(nx < 0 || ny < 0 || nx >= 5 || ny >= 5) continue;
if(!vis[nx][ny]) {
if(board[nx][ny] == 'O') {
q.push({nx, ny, cur.d + 1});
vis[nx][ny] = true;
}
else if(board[nx][ny] == 'P') return false;
}
}
}
return true;
}
vector<int> solution(vector<vector<string>> places) {
vector<int> answer;
for(auto& cur : places) {
board.assign(cur.begin(), cur.end());
bool flag = true;
for(int i=0; i<5 && flag; i++) {
for(int j=0; j<5; j++) {
if(board[i][j] == 'P') {
if(!bfs(i, j)) {
flag = false;
break;
}
}
}
}
if(flag) answer.push_back(1);
else answer.push_back(0);
}
return answer;
}
4. 소감