카테고리 없음

99클럽 코테 스터디 8일차 TIL - 탐색, 그리디, 비트마스킹

난쟁이 개발자 2024. 4. 20. 22:52
반응형

[Platinum IV] 불 끄기 - 14939

문제 링크

성능 요약

메모리: 114680 KB, 시간: 240 ms

분류

비트마스킹, 브루트포스 알고리즘, 그리디 알고리즘

제출 일자

2024년 4월 19일 17:07:51

문제 설명

전구 100개가 10×10 정사각형 모양으로 늘어서 있다. 전구에 달린 스위치를 누르면 그 전구와 위, 아래, 왼쪽, 오른쪽에 있는 전구의 상태도 바뀐다. 전구 100개의 상태가 주어지면 모든 전구를 끄기 위해 최소한으로 눌러야 하는 스위치의 개수를 출력하라

입력

10줄에 10글자씩 입력이 주어진다. #은 꺼진 전구고 O(대문자 알파벳 o)는 켜진 전구다. #과 O외에는 입력으로 주어지지 않는다.

출력

모든 전구를 끄기 위해 최소한으로 눌러야 하는 스위치의 개수를 출력하라. 불가능하면 -1를 출력하라.

 

풀이

더보기
import copy

dx = [0, -1, 1, 0, 0]
dy = [0, 0, 0, -1, 1]

def isValid(arr, x, y) :
    for d in range(5) :
        nx, ny = x + dx[d], y + dy[d]
        if 0 <= nx < 10 and 0 <= ny < 10 :
            arr[nx][ny] = not arr[nx][ny]

def solve(arr) :
    ans = float('inf')
    for first_row in range(1<<10) :   # 10개 전구에 대한 모든 조작 경우의 수
        cnt = 0
        narr = [copy.deepcopy(row) for row in arr]  # arr 상태 복사
        for i in range(10) :
            if first_row & (1 << i) :   # 첫 줄의 i번째 전구를 조작하는 경우
                isValid(narr, 0, i)
                cnt += 1

        for i in range(1, 10) : # 나머지 줄 처리
            for j in range(10) :
                if narr[i-1][j] :   # 위 전구가 켜져 있으면 해당 위치의 전구 조작
                    isValid(narr, i, j)
                    cnt += 1
        
        if all(not val for row in narr for val in row) :    # 모든 전구가 꺼져 있는지 확인
            ans = min(ans, cnt)

    return ans if ans != float('inf') else -1

arr = []
for _ in range(10) :
    row = list(map(lambda x: x == 'O', input().strip()))
    arr.append(row)

print(solve(arr))

브루트 포스 알고리즘을 사용하여 문제를 해결할 수 있었다. 전구의 상태를 변경하는 방식 때문에, 첫 번째 줄의 전구를 켜고 끄는 방식이 전체 패턴에 영향을 미치고 있다. 따라서, 첫 번째 줄의 모든 가능한 조합을 시도해보고, 그에 따라 나머지 줄들을 조정해가며 전구를 모두 끄는 최소 행위 횟수를 찾아야 한다.

  1. 첫 번째 줄에 있는 각 전구에 대해 켜지거나 꺼질 수 있는 모든 경우의 수(2 ^ 10 = 1024가지)를 고려
  2. 각 경우에 대해, 첫 번째 줄의 설정을 바탕으로 나머지 줄들에서 전구를 끄는 방법을 찾는다. 이 때, 현재 줄의 바로 위에 있는 전구가 켜져 있다면, 해당 전구를 끄기 위해 현재 줄의 해당 위치에 있는 스위치를 눌러야 한다.
  3. 모든 전구를 끌 수 있는 경우, 스위치를 누른 횟수를 기록. 모든 경우를 시도한 뒤, 가장 적은 횟수를 찾는다.
  4. 만약 모든 경우를 다 했음에도 모든 전구를 끌 수 없다면, -1을 출력 (아마 101가지보다 가지수가 많다면)

코드 구현은 첫 번째 줄의 스위치 조작을 통해 생성되는 모든 패턴을 시뮬레이션하여 나머지 줄들을 조절하는 방식으로 진행하였다. 이 과정에서 2차원 배열을 사용하여 전구의 상태를 저장하고 업데이트하는 방식을 채택하였다. 또한, 각 단계에서 스위치를 누를때마다 상, 하, 좌, 우의 전구 상태를 변경하는 함수를 구현하였다. 

 

문제를 해결하는데 있어 비트마스킹 활용하는 부분이나 구현하는 부분에 많은 어려움이 있어 구글 검색이나 GPT의 힘을 많이 빌렸다. 

반응형