0이면 꺼진 전구, 1이면 켜진 전구를 의미하는 전구들의 상태 A, B가 주어진다.
i번째 전구 스위치를 누르면, i-1, i, i+1
3개의 인접한 전구의 상태가 바뀐다.
A 상태를 B 상태로 바꾸기 위해 스위치를 최소 몇번 눌러야 하는지 구해야 한다.
바꾸는 것이 불가능할 수 있으며 이 경우 -1을 출력한다.
N = 3
A = 000
B = 010
110
으로 상태가 변한다001
으로 상태가 변한다.010
으로 상태가 변한다.총 3번 스위치를 눌렀고, A 상태에서 B 상태로 변경되었으므로 답은 3이다. (3보다 적게 누를 수 없음)
가령 위의 예제에서 1->0->2
순으로 누르거나, 2->1->0
으로 눌러도 똑같은 상태가 된다.
즉 누르는 순서를 신경쓸 필요 없이 0번 스위치부터 N-1번 스위치까지 순차적으로 돌면서 해당 스위치를 눌러도 될지 말지만 결정하면 된다.
다시 예제를 보자
A = 000
B = 010
110
이다.A[0] = B[0] = 0
이어야 하는데, 현재 110
상태에서 스위치를 누르지 않고 지나가면 A[0]
이 영원히 1이 되기 때문이다.001
이다.A[1] = B[1] = 1
이 되어야 하는데 현재 A[1] = 0
이기 때문이다.000
이다.A[0]
값이 영원히 1이 되기 때문이다. 여전히 A의 상태는 000
이다.A[1]
값이 1이 되어야 하기 때문이다. 그러나 2번째 스위치를 누르면 A의 상태는 011
이 되어 A != B
이다.즉 0번째 스위치만 누를지 말지만이 경우의 수이며, 나머지는 모두 A[i-1], B[i-1]
값에 따라 고정된다.
이를 코드로 구현하면 된다.
import sys
input = sys.stdin.readline
# 스위치를 눌렀을 때 상태 변경을 해주는 함수
def reverse(bulbs, count):
for i in range(1, N-1):
if bulbs[i-1] != target[i-1]:
count += 1
for j in range(i-1, i+2):
bulbs[j] = not bulbs[j]
# 마지막 전구만 따로 처리
if bulbs[N-1] != target[N-1]:
count += 1
bulbs[N-2] = not bulbs[N-2]
bulbs[N-1] = not bulbs[N-1]
if bulbs == target:
return count
else:
return -1
N = int(input())
# not을 이용해 간편하게 처리하고 싶어서 0:False, 1:True의 bool 값으로 바꾸었다.
off = list(map(bool, map(int, input().rstrip())))
# 0번째 스위치를 누른 상태를 저장하는 리스트
on = off.copy()
on[0] = not on[0]
on[1] = not on[1]
target = list(map(bool, map(int, input().rstrip())))
# 처음부터 상태가 같은 경우 스위치를 눌러줄 필요가 없으니 0 출력
if off == target:
print(0)
else:
# 0번째 전구를 안눌렀을 때
count = reverse(off, 0)
if count != -1:
print(count)
else:
# 0번째 전구를 눌렀을 때
count = reverse(on, 1)
print(count if count else -1)
그리디 유형의 문제를 많이 안풀어봐서 최근 많이 풀어보고 있는데, 확실히 난이도(티어)에 비해 많이 어렵게 느껴지는 것 같다.
단순히 그리디라고 하면 이득이면 하고, 아니면 말고 식의 문제인줄 알았는데
경우의 수를 고정해서 푸는 방법을 생각하지 못했다.
당분간 그리디를 많이 풀면서 익숙해지도록 하자.