BOJ/Gold

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

보단잉 2024. 3. 27. 21:06

문제 링크

문제

부유한 집안의 상속자 상근이네 집은 그림과 같이 1미터의 정육각형이 붙어있는 상태이다. 크리스마스가 다가오기 때문에, 여자친구에게 잘 보이기 위해 상근이는 건물의 벽면을 조명으로 장식하려고 한다. 외부에 보이지 않는 부분에 조명을 장식하는 것은 낭비라고 생각했기 때문에, 밖에서 보이는 부분만 장식하려고 한다.

 

 

위의 그림은 상공에서 본 상근이네 집의 건물 배치이다. 정육각형 안의 숫자는 좌표를 나타낸다. 여기서 회색 정육각형은 건물의 위치이고, 흰색은 건물이 없는 곳이다. 위에서 붉은 색 선으로 표시된 부분이 밖에서 보이는 벽이고, 이 벽에 조명을 장식할 것이다. 벽의 총 길이는 64미터이다.

상근이네 집의 건물 위치 지도가 주어졌을 때, 조명을 장식할 벽면의 길이의 합을 구하는 프로그램을 작성하시오. 지도의 바깥은 자유롭게 왕래 할 수 있는 곳이고, 인접한 건물 사이는 통과할 수 없다.

 

입력

첫째 줄에 두 개의 정수 W와 H가 주어진다. (1 ≤ W, H ≤ 100) 다음 H줄에는 상근이네 집의 건물 배치가 주어진다. i + 1줄에는 W개의 정수가 공백으로 구분되어 있다. j번째 (1 ≤ j ≤ w) 정수의 좌표는 (j, i)이며, 건물이 있을 때는 1이고, 없을 때는 0이다. 주어지는 입력에는 건물이 적어도 하나 있다.

지도는 다음과 같은 규칙에 의해 만들어졌다.

  • 지도의 가장 왼쪽 위에 있는 정육각형의 좌표는 (1, 1)이다.
  • (x, y)의 오른쪽에 있는 정육각형의 좌표는 (x + 1, y)이다.
  • y가 홀수 일 때, 왼쪽 아래쪽에 있는 정육각형의 좌표는 (x, y + 1)이다.
  • y가 짝수 일 때, 오른쪽 아래에 있는 정육각형의 좌표는 (x, y + 1)이다.

 

출력

조명을 장식하는 벽면의 길이의 합을 출력한다.

 

예제 입력 1

8 4
0 1 0 1 0 1 1 1
0 1 1 0 0 1 0 0
1 0 1 0 1 1 1 1
0 1 1 0 1 0 1 0

예제 출력 1

64

예제 입력 2

8 5
0 1 1 1 0 1 1 1
0 1 0 0 1 1 0 0
1 0 0 1 1 1 1 1
0 1 0 1 1 0 1 0
0 1 1 0 1 1 0 0

예제 출력 2

56

 

알고리즘 분류

  • 그래프 탐색

 

풀이

정육각형은 최대 6개의 정육각형과 맞닿아 있기 때문에 6방향으로 탐색해야 한다.

가장 먼저 W * H개의 정육각형 각각 어떤 정육각형과 맞닿아 있는지를 찾으며 건물이 있는 정육각형과 그냥 정육각형의 개수를 기록한다. 여기서 정육각형의 특정 변과 맞닿아 있는 정육각형이 없는 경우에는 그냥 정육각형으로 취급한다.

다음으로 건물이 위치한 정육각형 덩어리를 찾기 위해 BFS를 수행한다. 건물 덩어리의 길이는 각각의 정육각형과 맞닿아 있는 그냥 정육각형의 개수의 총합이다. 이 값을 계속 누적시킨다.

여기서 건물 덩어리 안에 위치해있는 그냥 정육각형이 있음을 고려해야 한다. 역시 BFS로 그냥 정육각형 덩어리를 찾는다.

그냥 정육각형 덩어리의 길이는 각각의 정육각형과 맞닿아 있는 건물이 위치한 정육각형의 개수의 총합이며, 이 값을 빼 주어야 진정한 벽면의 길이를 구할 수 있다.

 

코드

더보기
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <algorithm>
#define MAX 101
#define FASTIO cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);

using namespace std;
int W, H;
int MAP[MAX][MAX];
int adjacent[MAX][MAX][2];
bool Visited[MAX][MAX];
int MoveY[2][6] = { { -1,-1,0,1,1,0 }, { -1,-1,0,1,1,0 } };
int MoveX[2][6] = { { 0,1,1,1,0,-1 }, { -1,0,1,0,-1,-1 } };
int Answer;

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

int bfs(int Y, int X, int V) {
    queue<pair<int, int> > Q;
    Visited[Y][X] = true;
    Q.push(make_pair(Y, X));
    int Result = 0;

    while (!Q.empty()) {
        int NowY = Q.front().first;
        int NowX = Q.front().second;
        Q.pop();

        if (Result != -1) {
            Result += adjacent[NowY][NowX][!V];
        }

        for (int i = 0; i < 6; i++) {
            int NextY = NowY + MoveY[NowY % 2][i];
            int NextX = NowX + MoveX[NowY % 2][i];
            if ((NextY >= 0) && (NextY < H) && (NextX >= 0) && (NextX < W)) {
                if (!Visited[NextY][NextX] && (MAP[NextY][NextX] == V)) {
                    Visited[NextY][NextX] = true;
                    Q.push(make_pair(NextY, NextX));
                }
            }
            else {
                if (V == 0) {
                    Result = -1;
                }
            }
        }
    };

    if (Result == -1) {
        Result = 0;
    }

    return Result;
}

void settings() {
    for (int i = 0; i < H; i++) {
        for (int j = 0; j < W; j++) {
            for (int k = 0; k < 6; k++) {
                int NextY = i + MoveY[i % 2][k];
                int NextX = j + MoveX[i % 2][k];
                if ((NextY >= 0) && (NextY < H) && (NextX >= 0) && (NextX < W)) {
                    if (MAP[NextY][NextX] == 1) {
                        adjacent[i][j][1]++;
                    }
                    else {
                        adjacent[i][j][0]++;
                    }
                }
                else {
                    adjacent[i][j][0]++;
                }
            }
        }
    }
    for (int i = 0; i < H; i++) {
        for (int j = 0; j < W; j++) {
            if (!Visited[i][j]) {
                if (MAP[i][j] == 1) {
                    Answer += bfs(i, j, 1);
                }
                else {
                    Answer -= bfs(i, j, 0);
                }
            }
        }
    }
}

void find_Answer() {
    cout << Answer << "\n";
}

int main() {
    FASTIO
    input();
    settings();
    find_Answer();

    return 0;
}