Henu
개발냥발
Henu
전체 방문자
오늘
어제
  • 분류 전체보기 (411)
    • DevOps (52)
      • Kubernetes (19)
      • Docker (14)
      • AWS (3)
      • Nginx (4)
      • Linux (4)
      • ArgoCD (1)
      • CN (2)
      • NATS (0)
      • Git (5)
    • Back-End (30)
      • Django (18)
      • Spring (5)
      • JPA (1)
      • MSA (5)
    • CS (87)
      • SystemSoftware (20)
      • OS (25)
      • Computer Architecture (16)
      • Network (23)
      • Database (2)
    • Lang (21)
      • Java (9)
      • Python (4)
      • C# (8)
    • Life (12)
    • 블록체인 (2)
    • Algorithm (204)
      • BOJ (160)
      • 프로그래머스 (19)
      • LeetCode (4)
      • SWEA (1)
      • 알고리즘 문제 해결 전략 (8)
      • DS, algorithms (7)
      • Checkio (5)
    • IT (2)

블로그 메뉴

  • GitHub
  • 글쓰기
  • 관리자

공지사항

  • Free!

인기 글

태그

  • docker
  • 백트래킹
  • DFS
  • boj
  • BFS
  • 다이나믹 프로그래밍
  • Kubernetes
  • django
  • 프로그래머스
  • Network

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Henu

개발냥발

[백준 5547] 일루미네이션 (C++)
Algorithm/BOJ

[백준 5547] 일루미네이션 (C++)

2022. 1. 19. 09:20
 

5547번: 일루미네이션

첫째 줄에 두 개의 정수 W와 H가 주어진다. (1 ≤ W, H ≤ 100) 다음 H줄에는 상근이네 집의 건물 배치가 주어진다. i+1줄에는 W개의 정수가 공백으로 구분되어 있다. j번째 (1 ≤ j ≤ w) 정수의 좌표는

www.acmicpc.net

 

 

BFS 구현 문제이다

 

 

위 그림에서 2,3 좌표는 비어있는데 건물에 둘러싸인 '내부 공간'이다.

 

건물이 좌표 바깥이나 외부 공간과 맞닿아 있다면 답을 +1 해주면 되는데, 내부 공간이라는 변수 때문에 단순한 bfs로는 풀리지 않는다.

 

따라서 빈 공간이 내부 공간인지, 외부 공간인지를 미리 판단 해 놓아야 한다.

 

 

그걸 어떻게 판단하는가?

하나 이상으로 이어진 외부 공간은 좌표 바깥 부분과 맞닿아있다. 따라서 좌표의 경계선에 위치한 빈 공간에서 BFS를 수행하면, BFS 도중에 만난 빈 공간들은 모두 외부 공간이 된다.

따라서 나는 외부 공간을 '2'라는 숫자로 표시 해주었다.(입력은 0, 1로만 주어진 상태)

 

 

사전 작업이 완료되면 건물에서 시작하는 BFS를 수행한다.

if(nx < 1 || nx > W || ny < 1 || ny > H || Map[nx][ny] == 2){
    ret++;
    continue;
}

BFS를 돌면서 현재 건물에서 움직일 수 있는 다음 칸이 좌표 바깥이거나 외부 공간('2')인 경우 답을 +1 해준다.

 

 

 

6방향 탐색 방법

int odx[6] = {1, 1, 1, 0, -1, 0};
int ody[6] = {-1, 0, 1, 1, 0, -1};
int edx[6] = {0, 1, 0, -1, -1, -1};
int edy[6] = {-1, 0, 1, 1, 0, -1};

...

int nx = x + (y % 2? odx[i]: edx[i]);
int ny = y + (y % 2? ody[i]: edy[i]);

현재 칸의 y좌표가 홀수인지, 짝수인지에 따라서 좌표의 이동이 달라진다.

따라서 짝수 이동을 담당하는 ed와 홀수 이동을 담당하는 od 배열을 정의해주었다. (2시방향부터 시계방향으로 돌아감)

 

그리고 삼항 연산자를 사용해서 현재 y좌표에 따라서 od를 적용할 지 ed를 적용할 지를 정해주었다.

 

 

 

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <cstring>
#define fasti ios_base::sync_with_stdio(false); cin.tie(0);
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define INF 1e9+7
#define pii pair<int, int>

typedef long long ll;
// typedef pair<int, int> pii;

using namespace std;

int W, H;
int Map[101][101];

int odx[6] = {1, 1, 1, 0, -1, 0};
int ody[6] = {-1, 0, 1, 1, 0, -1};
int edx[6] = {0, 1, 0, -1, -1, -1};
int edy[6] = {-1, 0, 1, 1, 0, -1};

void input(){
    cin >> W >> H;
    for(int i = 1; i <= H; i++){
        for(int j = 1; j <= W; j++){
            cin >> Map[j][i];
        }
    }
}

void bfs1(pii start){
    queue<pii > que;
    que.push(start);
    
    bool visited[101][101];
    memset(visited, 0, sizeof(visited));
    visited[start.first][start.second] = true;
    
    while(!que.empty()){
        int x = que.front().first;
        int y = que.front().second;
        que.pop();
        
        Map[x][y] = 2;
        
        for(int i = 0; i < 6; i++){
            int nx = x + (y % 2? odx[i]: edx[i]);
            int ny = y + (y % 2? ody[i]: edy[i]);
            
            if(nx < 1 || nx > W || ny < 1 || ny > H || \
            visited[nx][ny] || Map[nx][ny] == 1) continue;
            
            visited[nx][ny] = true;
            que.push({nx, ny});
        }
    }
}

bool Tvisited[101][101];
int bfs2(pii start){
    int ret = 0;
    
    queue<pii > que;
    que.push(start);
    
    Tvisited[start.first][start.second] = true;
    
    while(!que.empty()){
        int x = que.front().first;
        int y = que.front().second;
        que.pop();
        
        for(int i = 0; i < 6; i++){
            int nx = x + (y % 2? odx[i]: edx[i]);
            int ny = y + (y % 2? ody[i]: edy[i]);
        
            if(Tvisited[nx][ny]) continue;
            if(nx < 1 || nx > W || ny < 1 || ny > H || Map[nx][ny] == 2){
                ret++;
                continue;
            }
            if(Map[nx][ny] == 0) continue;
            
            Tvisited[nx][ny] = true;
            que.push({nx, ny});
        }
    }
    
    return ret;
}


void solve(){
    // 가운데 들어간 빈 공간이 문제
    
    // 빈 공간이 건물 내부인지 외부인지 판별
    for(int i = 1; i <= W; i++){
        for(int j = 1; j <= H; j++){
            if(Map[i][j] == 1) continue;
            if(i == 1 || j == 1 || i == W || j == H){
                bfs1({i, j});
            }
        }
    }
    
    // 건물 내부의 빈 공간이면 0, 외부의 빈 공간이면 2, 건물이면 1
    int answer = 0;
    
    memset(Tvisited, 0, sizeof(Tvisited));
    for(int i = 1; i <= W; i++){
        for(int j = 1; j <= H; j++){
            if(Map[i][j] == 0 || Map[i][j] == 2 || Tvisited[i][j]) continue;
            answer += bfs2({i, j});
        }
    }
    cout << answer;
}

int main(){
    fastio
    input();
    solve();
    
    return 0;
}

'Algorithm > BOJ' 카테고리의 다른 글

[백준 16637] 괄호 추가하기 (C++)  (0) 2022.04.24
[백준 14867] 물통 (C++)  (0) 2022.01.19
[백준 2836] 수상 택시 (C++)  (0) 2022.01.12
[백준 4095] 최대 정사각형 (C++)  (0) 2022.01.11
[백준 1280] 나무심기 (C++)  (0) 2022.01.09
    'Algorithm/BOJ' 카테고리의 다른 글
    • [백준 16637] 괄호 추가하기 (C++)
    • [백준 14867] 물통 (C++)
    • [백준 2836] 수상 택시 (C++)
    • [백준 4095] 최대 정사각형 (C++)

    티스토리툴바