[Python] 백준 5527 일루미네이션

2022. 7. 11. 15:20·CS/알고리즘 & 문제풀이

문제 링크 : https://www.acmicpc.net/problem/5547

 

5547번: 일루미네이션

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

www.acmicpc.net

 

1. 접근 방법

BFS를 응용하여 해결하는 문제인데, 육각형 구조에 따라 추가적인 고려사항이 생긴 문제이다.

그리고 단순히 육각형의 수를 원하는 것이 아니라 모서리의 길이를 구하여야 하므로, 조금 더 복잡한 과정이 필요할 수 있다.

 

처음에는 각 선분을 좌표로 하여 탐색하려 했다. 어차피 한붓그리기 형태가 될 것이므로 구현은 조금 복잡할 수 있지만, 쉽게 구할 수 있을 것 같았다. 하지만, 방문 확인하는 것과 문제에서 주어진 첫 번째 예시처럼 내부의 공간이 있을 때 잡아내지 못할 것 같았다.

그다음에는 각각 덩어리를 구하여 외부 선분을 찾으려 했는데, 이 경우는 배치되는 모양에 따라 많이 복잡해질 수 있을 것 같았다.

 

그래서 건물(1)을 확인하는 대신 빈 공간(0)을 확인하여 벽의 수를 구했다.


2. 풀이 코드

🖥python 코드 링크 : https://github.com/mintropy/PS/blob/master/BAEKJOON/Python/5000/5500/5547.py

 

GitHub - mintropy/PS: 다양한 알고리즘 문제 풀이 저장소입니다.

다양한 알고리즘 문제 풀이 저장소입니다. Contribute to mintropy/PS development by creating an account on GitHub.

github.com

📕코드 해설

앞서 이 문제를 해결하기 위한 두가지 방법을 소개하면 다음과 같다.

첫 번째는 탐색방법이다. 우선 문제에서 주어진 것과 좌표를 다른 방향으로 두어 계산했는데, 이는 큰 문제는 되지 않을 것 같다.

이때, 위에서부터 짝수, 홀수 줄에 따라 6방향 탐색을 살펴보면, 좌표의 변환이 다르다. 그래서 위에서부터 몇 번째 줄이냐에 따라 탐색을 다르게 해야 한다. 따라서 다음과 같이 델타를 설정했다.

delta = [
    [(-1, 0), (0, 1), (1, 0), (1, -1), (0, -1), (-1, -1)],
    [(-1, 1), (0, 1), (1, 1), (1, 0), (0, -1), (-1, 0)],
]

 

다음으로 빨간색이 건물, 파란색이 빈 공간이라 할 때, 벽을 탐색하는 과정이다.

각 위치에서 인접한 건물의 개수를 파악한다. 예를 들어 (1,1)에서 1개, (1,2)에서 2개와같은 방식이다. 그리고 이 인접한 건물의 수에 따라 벽의 수가 정해 지므로, 이 숫자들을 누적하여 기록해두면 된다.

그런데 만약 (2,1)이나 (1,3)처럼 가장 바깥부분이 건물이면 어떻게 처리하면 좋을까? 그래서 외부에 0으로 패딩을 두고 탐색했다.

walls = (
    [[0] * (W + 2)] + [[0] + list(MIIS()) + [0] for _ in range(H)] + [[0] * (W + 2)]
)

 

각 위치별 육각형 탐색과, 벽의 개수 탐색 두부분을 적절히 활용하면 문제를 해결할 수 있다.

 

queue = deque([(0, 0)])
while queue:
    x, y = queue.popleft()
    if visited[x][y]:
        continue
    visited[x][y] = True
    ans += count_walls(x, y)
    count[x][y] = count_walls(x, y)
    for dx, dy in delta[x % 2]:
        nx, ny = x + dx, y + dy
        if 0 <= nx <= H + 1 and 0 <= ny <= W + 1:
            if not walls[nx][ny]:
                queue.append((nx, ny))

deque를 하나 선언하여, 가장 외부에서 시작했다. 어차피 벽은 외부와 연결돼있을 것이라 생각하여 패딩 한 부분에서 시작을 했고, 추가적인 조건문이나 탐색과정을 생략 할 수 있다.

 

def count_walls(x: int, y: int) -> int:
    global walls, delta
    count = 0
    for dx, dy in delta[x % 2]:
        nx, ny = x + dx, y + dy
        if 0 <= nx <= H + 1 and 0 <= ny <= W + 1:
            if walls[nx][ny]:
                count += 1
    return count

벽의 개수는 6방향 탐색을 통하여 해결했다.


3. 생각 정리

육각형 탐색의 몇몇 문제를 보았는데, 이 문제는 모서리의 길이를 구하는 것이라 조금 고민했다. 같은 방식을 사용한다면 사각형 등의 경우도 유사하게 해결할 수 있을 것 같다.

 

 

 

'CS > 알고리즘 & 문제풀이' 카테고리의 다른 글

[Python] 백준 1655 가운데를 말해요  (0) 2022.08.03
[Python] 백준 20149 선분교차 3  (0) 2022.07.25
[알고리즘] 이분 매칭(Bipartite Matching)  (0) 2022.05.22
[Python] 백준 3806 S를 T로  (0) 2022.04.17
[Python] 2212 센서  (0) 2022.03.25
'CS/알고리즘 & 문제풀이' 카테고리의 다른 글
  • [Python] 백준 1655 가운데를 말해요
  • [Python] 백준 20149 선분교차 3
  • [알고리즘] 이분 매칭(Bipartite Matching)
  • [Python] 백준 3806 S를 T로
mintropy
mintropy
민트로피의 하루하루 오늘보다 더 나은 내일
  • mintropy
    민트로피의 민트초코
    mintropy
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 생각 정리
        • 코딩테스트
        • SSAFY
      • 디지털 노트
        • Obsidian.md
        • Notion
      • CS
        • 알고리즘 & 문제풀이
        • AI
        • DB
        • 디자인패턴
      • Projects
      • Python
        • Python Web Framework
      • JavaScript
        • React.js
      • Docker
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    markdown
    pydantic
    백준
    조건분기
    알고리즘
    bfs
    union-find
    파이썬
    SSAFY
    Python
    코딩테스트
    게임이론
    구현
    dfs
    ps
    프로젝트
    fastapi
    django
    trie
    브루트포스
    그리디
    프로그래머스
    카카오
    회고
    Combinatorics
    DRF
    DP
    web framework
    line
    project_zero
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
mintropy
[Python] 백준 5527 일루미네이션
상단으로

티스토리툴바