📌 문제
강호는 전구 N개를 가지고 있다. 전구는 1번부터 N번까지 번호가 매겨져 있으며, 일렬로 놓여져 있다. 전구는 켜져있거나 꺼져있다.
강호는 모든 전구를 끄려고 한다. 강호는 전구를 켜고 끌 수 있는 스위치 N개를 가지고 있고, 스위치도 1번부터 N번까지 번호가 매겨져 있다. i번 스위치는 i의 배수 번호를 가지는 전구의 상태를 모두 반전시킨다.
현재 전구의 상태가 주어졌을 때, 모든 전구를 끄기 위해서 스위치를 몇 번 눌러야하는지 구하는 프로그램을 작성하시오.
입력
첫째 줄에 전구의 상태가 1번 전구부터 차례대로 주어진다. Y는 전구가 켜 있는 경우, N은 전구가 꺼져있는 경우이다. 전구의 개수는 1보다 크거나 같고 1,000보다 작거나 같은 자연수이다.
출력
모든 전구를 끄기 위해서 스위치를 몇 번 눌러야 하는지 출력한다. 만약, 모든 전구를 끌 수 없다면 -1을 출력한다.
예제 입력1
YYYYYY
예제 출력1
1
예제 입력2
YNYNYNYNY
예제 출력2
2
예제 입력3
NNNNNNNNNN
예제 출력3
0
예제 입력4
YYYNYYYNYYYNYYNYYYYN
예제 출력4
4
📌 풀이
Code
import sys
input = sys.stdin.readline
bulbs = ['N'] + list(input().strip()) # 전구 상태 목록 (인덱스를 편리하게 확인하기 위해 앞에 N 붙이기)
N = len(bulbs) # 전구 개수
cnt = 0 # 스위치 누른 횟수
for i in range(1, N):
if bulbs[i] == 'Y': # 켜져있는 전구를 만나면
for j in range(i, N, i): # 해당 번호 배수인 전구 상태 변경
if bulbs[j] == 'Y':
bulbs[j] = 'N'
else:
bulbs[j] = 'Y'
cnt += 1 # 스위치 한번 누름
print(cnt)
Solution
1. 전구 상태를 입력으로 받고, 인덱스를 편리하게 확인하기 위해 리스트 맨 앞에 원소 하나를 추가하기
2. 1번 전구부터 N번 전구까지 켜져 있는 전구 탐색
3. 켜져 있는 전구를 만나면 해당 번호 배수인 전구 상태 변경
4. 전구 상태를 변경 시킬 때 마다(스위치를 누를 때 마다) 카운트 1 증가
5. 최종 카운트 반환
깨달은 점
저는 처음에 이 문제의 조건을 보고 굉장히 복잡하게 생각했습니다.
켜져 있는 전구 리스트를 받은 뒤에 최대공배수를 계산해야하나? 끝까지 다 끌 수 없는 경우는 뭐지?
그러나!! 이 모든 것은 함정이었다는 것...
이 문제의 핵심은 바로 "모든 전구를 끌 수 없는 경우는 존재하지 않는다" 입니다.
생각해보면 당연한게, 자신의 배수는 자기 자신도 포함하기 때문입니다.
그러니, 앞에서부터 차례로 켜져 있는 전구 스위치를 끄다보면 결국 마지막엔 무조건 다 끌 수 있다는 거죠...
이 아이디어를 얻은 시점에도 사실 긴가민가 했습니다.
앞에서부터 차례로 스위치를 눌러도 정말 최적해를 찾을 수 있을까..?
좀 찝찝하지 않습니까?
찝찝한 그 느낌! 그것이 바로 그리디입니다!
Greedy Algorithm : 지금 당장 가질 수 있는 최고의 이익을 따라가는 알고리즘
물론 그리디가 모든 경우에 최적해를 보장하지는 못하지만,
드물게 최적해를 낼 수 있는 경우도 있습니다. 이 문제가 그런 경우에 해당하죠!
이 문제에서 그리디 알고리즘이 최적해를 찾을 수 있는 이유는 특정 전구의 상태를 변경하는 스위치가 고유하게 그 전구의 상태만 반전시키기 때문입니다.
i번 스위치는 i의 배수인 전구들만 조작하며, 이 과정에서 특정 전구가 여러 번 상태를 반전하게 되지만, 결과적으로 마지막에 이 전구가 꺼지도록 조작됩니다.
그리디 알고리즘은 각 단계에서 가장 최적인 선택을 하면서 진행하기 때문에,
전구를 모두 끄기 위해 필요한 최소한의 스위치 조작 횟수를 보장할 수 있습니다.
앞으로는 각 단계마다 지역 최적해를 찾는 문제,
즉 문제를 더 작게 줄여나가는 형태가 보이면 그리디를 떠올려야겠습니다!
'Coding Test > Baekjoon' 카테고리의 다른 글
[백준] 14502 연구소(Python) - BFS, Backtraking (0) | 2024.10.02 |
---|---|
[백준] 10711 모래성(Python) - BFS (2) | 2024.08.28 |
[백준] 10026 적록색약(Python) - BFS (0) | 2024.08.22 |
[백준] 2669 직사각형 네개의 합집합의 면적 구하기(Python) - Simulation (0) | 2024.08.18 |