HJW's IT Blog

[프로그래머스/C++] 거리두기 확인하기 본문

Algorithm

[프로그래머스/C++] 거리두기 확인하기

kiki1875 2024. 9. 10. 14:43

문제 분석

이 문제는 카카오 대기실에서 면접 응시자들이 코로나 바이러스 예방을 위해 적절한 거리를 두고 있는지를 확인하는 문제입니다. 주어진 조건을 기반으로 대기실에서 응시자들이 거리두기 규칙을 준수했는지를 판단해야 합니다.

대기실의 구조는 5x5 크기의 2차원 배열로 주어지며, 배열의 각 원소는 다음과 같습니다:

  • P: 응시자가 앉아 있는 자리
  • O: 빈 테이블
  • X: 파티션

거리두기 규칙

  1. 응시자들 사이의 거리는 맨해튼 거리로 계산되며, 거리가 2 이하인 경우 규칙을 위반하게 됩니다.
  2. 만약 두 응시자 사이에 파티션이 있으면 거리가 2 이하여도 규칙을 위반하지 않습니다.

핵심

  1. 맨해튼 거리 2 이하의 응시자 사이에 파티션이 없다면 거리두기를 지키지 않은 것입니다.
  2. 각 응시자별로 주변을 탐색하며 위의 규칙을 충족하는지 확인해야 합니다.

문제 풀이 접근 방법

  1. 각 대기실 탐색: 5개의 대기실을 차례대로 확인합니다.
  2. 응시자 주변 탐색: 각 응시자의 위치에서 너비 우선 탐색(BFS)을 사용해 맨해튼 거리 2 이내에 있는 다른 응시자가 있는지 확인합니다.
    • 탐색 도중 파티션이 있으면 탐색을 중단하고 다른 방향을 탐색합니다.
    • 응시자(P)를 발견하면 거리두기를 지키지 않은 것으로 간주하고 탐색을 종료합니다.

코드

#include <bits/stdc++.h>
using namespace std;

// 상, 하, 좌, 우 방향을 위한 배열
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};

// 두 좌표의 맨해튼 거리를 계산하는 함수
int dist(int x1, int y1, int x2, int y2) {
    return abs(x1 - x2) + abs(y1 - y2);
}

// BFS를 사용하여 응시자들 간 거리두기 규칙을 확인하는 함수
bool bfs(vector<string>& room, int x, int y) {
    // 방문 체크 배열
    vector<vector<bool>> visited(room.size(), vector<bool>(room[0].length(), false));
    // BFS 탐색을 위한 큐 (현재 거리, 좌표)
    queue<pair<int, pair<int, int>>> q;

    q.push({0, {x, y}});
    visited[x][y] = true;

    while (!q.empty()) {
        int cx = q.front().second.first;  // 현재 x 좌표
        int cy = q.front().second.second; // 현재 y 좌표
        int cost = q.front().first;       // 현재까지의 거리
        q.pop();

        // 상, 하, 좌, 우 4방향 탐색
        for (int i = 0; i < 4; i++) {
            int nx = cx + dx[i];
            int ny = cy + dy[i];
            int nCost = cost + 1;

            // 범위를 벗어나면 무시
            if (nx < 0 || ny < 0 || nx >= room.size() || ny >= room[0].length()) continue;
            // 이미 방문한 곳은 무시
            if (visited[nx][ny]) continue;
            // 파티션이면 탐색 종료
            if (room[nx][ny] == 'X') continue;

            // 거리 계산
            int distance = dist(nx, ny, x, y);

            // 응시자가 있는 경우 거리두기 규칙 위반 확인
            if (room[nx][ny] == 'P' && (nCost < 3 || distance < 2)) return false;
            visited[nx][ny] = true;
            q.push({nCost, {nx, ny}});
        }
    }

    return true;
}

// 대기실에서 거리두기 규칙을 지키고 있는지 확인하는 함수
bool check(vector<string>& room) {
    for (int i = 0; i < room.size(); i++) {
        for (int j = 0; j < room[i].length(); j++) {
            // 응시자가 앉아 있는 자리(P)에서 거리두기 규칙 확인
            if (room[i][j] == 'P') {
                if (!bfs(room, i, j)) return false;
            }
        }
    }
    return true;
}

// 문제 해결 함수
vector<int> solution(vector<vector<string>> places) {
    vector<int> answer;

    // 각 대기실에 대해 거리두기 규칙 확인
    for (auto room : places) {
        if (check(room)) answer.push_back(1); // 규칙을 지킨 경우
        else answer.push_back(0);             // 규칙을 위반한 경우
    }

    return answer;
}