Gom3rye

작심 큰일 챌린지 - 초콜릿 괴도 코코 (Sweet) (파이썬) 본문

현대 오토에버 클라우드 스쿨

작심 큰일 챌린지 - 초콜릿 괴도 코코 (Sweet) (파이썬)

Gom3rye 2025. 8. 7. 16:59
728x90
반응형
새로 배운 개념이나 기술:
남은 노드들이 모두 연결이 되어 있지만 사이클이 없으려면 트리 구조를 이루어야 한다. 트리 구조는 무방향 그래프에서 모든 노드가 사이클 없이 연결되어 있고, v(노드 수)-e(간선 수) == 1로 확인할 수 있다.
1개였던 덩어리에서 2개 이상으로 덩어리가 끊어졌는지 아닌지를 확인하기 위해선 bfs를 돌리면서 방문한 노드의 수와 원래 덩어리 수를 비교해보면 알 수 있다.
bfs 돌릴 때) 남아 있는 초콜릿들을 빠르게 조회하기 위해 set을 사용할 수 있고 대신 set은 순서가 보장되지 않은 자료 구조니까 리스트처럼 인덱스를 사용해 첫 원소를 q에 넣어줄 수 없고 next(iter(remaining)을 써야 한다.

어려웠던 점과 해결 방법:
조건1과 조건2를 모두 만족하도록 코드를 짜는 것이 어려웠다. 아무래도 조건이 많아 지면 구현이 복잡해지니까 덜컥 겁을 먹는 것 같은데 앞으로는 만족해야 하는 조건을 한꺼번에 만족하도록 구현하는 것 보다 하나 하나 만족하도록 단계적으로 코드를 작성한 후 결과적으로 조건들을 모두 만족하도록 짜야 겠다고 생각했다.

 

 

import sys
input = sys.stdin.readline
from collections import deque
def solution():
    n = int(input())
    board = [list(input().strip()) for _ in range(n)]
    # 사이클을 가능하게 하는 지점을 떼어내야 조건을 만족할 수 있다.

    # 1. 초콜릿들 위치 저장
    chocolates = []
    for i in range(n):
        for j in range(n):
            if board[i][j] == '#':
                chocolates.append((i, j))
    
    choco = len(chocolates)
    answers = []
    # 2. 각 초콜릿을 한 번씩 떼어보는 시뮬레이션
    for i in range(choco):
        removed = chocolates[i]

        # 떼어낸 후 남은 초콜릿들의 집합 (빠른 조회를 위해 set사용)
        remaining = set(chocolates)
        remaining.remove(removed)

        # 조건1. 연결성 확인 (bfs)
        directions = [(0,1), (0,-1), (1,0), (-1,0)]
        # remaining이 set이라 순서가 없으니 맨 앞 하나 꺼내려면 이렇게 해야 한다.
        start = next(iter(remaining))
        q = deque([start])
        visited = {start}
        while q:
            x, y = q.popleft()
            for dx, dy in directions:
                nx, ny = dx+x, dy+y
                if (nx, ny) in remaining and (nx, ny) not in visited:
                    visited.add((nx, ny))
                    q.append((nx, ny))

        # bfs 후 방문한 개수가 남은 초콜릿 수와 다르면 조각이 나뉜 것
        if len(visited) != len(remaining):
            continue

        # 조건2. 사이클 확인 (v-e=1)
        v = len(remaining)
        e = 0
        # 간선 개수 세기 (중복 방지를 위해 오른쪽, 아래쪽만 확인)
        for x, y in remaining:
            if (x, y+1) in remaining: # 오른쪽 확인
                e += 1
            if (x+1, y) in remaining: # 아래쪽 확인
                e += 1
        
        # 연결 그래프가 트리이려면 v-e=1 이어야 한다.
        if v-e == 1:
            # 두 조건 모두 만족시 정답에 추가 (좌표는 1based index)
            answers.append((removed[0]+1, removed[1]+1))
    
    # 최종 출력
    print(len(answers))
    for x, y in answers:
        print(x, y)

solution()
728x90
반응형

'현대 오토에버 클라우드 스쿨' 카테고리의 다른 글

Ansible- 변수  (0) 2025.08.08
Ansible  (0) 2025.08.07
작심 큰일 챌린지 - 컵라면 (파이썬)  (3) 2025.08.06
AWS- 로그 관리와 운영  (5) 2025.08.06
작심 큰일 챌린지 - 냅색 문제 (파이썬)  (3) 2025.08.05