본문 바로가기
[Python] Baekjoon/Greedy(그리디)

[백준(Baekjoon)] 2138 전구와 스위치

by 파크영 2021. 12. 13.

문제

N개의 스위치와 N개의 전구가 있다. 각각의 전구는 켜져 있는 상태와 꺼져 있는 상태 중 하나의 상태를 가진다. i(1 < i < N)번 스위치를 누르면 i-1, i, i+1의 세 개의 전구의 상태가 바뀐다. 즉, 꺼져 있는 전구는 켜지고, 켜져 있는 전구는 꺼지게 된다. 1번 스위치를 눌렀을 경우에는 1, 2번 전구의 상태가 바뀌고, N번 스위치를 눌렀을 경우에는 N-1, N번 전구의 상태가 바뀐다.

N개의 전구들의 현재 상태와 우리가 만들고자 하는 상태가 주어졌을 때, 그 상태를 만들기 위해 스위치를 최소 몇 번 누르면 되는지 알아내는 프로그램을 작성하시오.

 

입력

첫째 줄에 자연수 N(2 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 전구들의 현재 상태를 나타내는 숫자 N개가 공백 없이 주어진다. 그 다음 줄에는 우리가 만들고자 하는 전구들의 상태를 나타내는 숫자 N개가 공백 없이 주어진다. 0은 켜져 있는 상태, 1은 꺼져 있는 상태를 의미한다.

 

출력

첫째 줄에 답을 출력한다. 불가능한 경우에는 -1을 출력한다.

 

예제 입력 1 

3
000
010

예제 출력 1 

3

 


나의 코드

[Python(파이썬)]

def two_bulb(one, two):
    before[one] = 1 - before[one]
    before[two] = 1 - before[two]

def three_bulb(one, two, three):
    before[one] = 1 - before[one]
    before[two] = 1 - before[two]
    before[three] = 1 - before[three]

import sys

input = sys.stdin.readline
n = int(input())
before = [0] + list(map(int, input().strip()))
after = [0] + list(map(int, input().strip()))
n1, n2 = before[:], before[:]

if before == after:  # 시작할 때 같은 경우
    print(0)
else:
    for j in range(2):  # j=0: 1번 스위치 누름, j=1: 1번 스위치 누르지 않음
        before = n1 if j == 0 else n2
        cnt = 0

        if j == 0:  # 1번 스위치 누른 경우
            two_bulb(1, 2)
            cnt += 1

        for i in range(2, n + 1):
            if before[i - 1] != after[i - 1]:
                if i <= n - 1:  # 2~(n-1)번 스위치
                    three_bulb(i - 1, i, i + 1)
                    cnt += 1
                elif i == n:  # n번 스위치
                    two_bulb(i - 1, i)
                    cnt += 1

        if before == after:
            print(cnt)
            break

    if before != after:
        print(-1)

 


풀이

처음 '틀렸습니다'가 나온 이유

 

처음 이 문제를 풀 때 예제도 통과하고 10%까지 올라가다가 틀렸습니다가 나오길래 대체 뭐가 문제인가 한참을 고민했다. 그러다 깨닫게 된 치명적 오류,,, n번 스위치를 누르기 위해서 (1~n)스위치를 모두 눌러야하는 것이 아니었다. 

문제에는 n번을 누르기위해서는 (1~n-1)스위치를 모두 눌러야한다라는 어떠한 말도 없었는데 왜 착각을 했는지ㅠㅠ

즉, 3번을 누르기 위해서는 1, 2, 3번 순서대로 눌러야한다고 생각했다. 하지만 1번과 3번만 눌러도 되고 3번 한 개만 눌러도 되는 것이다. 

따라서 문제를 풀 때 왼쪽 첫 전구부터 오른쪽 끝 전구까지 체크하면서 스위치를  누를 것인가 체크해주면 된다. 

 

 

1. 2 ~ n번 스위치 선택 유무

 

위 그림에서 2번 스위치를 누르게 된다면 빨간색 네모칸인 1, 2, 3번 전구의 상태가 변화된다. 

왼쪽에서 오른쪽으로 이동하며 스위치를 누를 지 결정하기 때문에 1번 전구의 상태를 변화시킬 마지막 기회는 2번 스위치이다.

3번 스위치로 이동하게 되면 2, 3, 4번 전구의 상태가 변화하기 때문에 1번은 더이상 변화할 수 없는 것이다.

따라서 스위치를 누를 것인가는 파란색 동그라미 왼쪽에 있는 전구의 상태를 보고 결정해야 한다. 

 

 

 

2. 1번 스위치 선택 유무

 

1번에 말 대로라면 i번 스위치는 i-1 전구를 보고 누를지 말지 결정하는데 1번 스위치는 0번 스위치가 없기 때문에 눌러야할지 말아야할지 결정할 수 없다. 

따라서 1번 스위치를 눌렀을 경우, 누르지 않았을 경우 두가지로 나눠서 생각해야한다.

 

 

 

구현 순서

 

1) 1번 스위치를 누르는 경우, 누르지 않는 경우 두가지로 나눈다. 
2) 1번 스위치를 누른 경우 
2-1) i-1번 전구를 확인하고 2~n번 전구까지 이동하며 누를지 말지 결정한다. 
2-2) n번 스위치 선택 여부까지 결정 한 후 만들고자 하는 상태가 되었는지 확인한다. 
2-3) 만들고자 하는 상태가 되었다면 스위치 누른 횟수를 출력 하고 프로그램 종료
2-4) 만들고자 하는 상태가 되지 않았다면 3)번 으로 계속 진행
3) 1번 스위치를 누르지 않은 경우
3-1) 2번과 똑같이 진행
4) 만들고자 하는 상태가 아직도 되지 않았다면 불가능하므로 -1 출력 

 


문제 출처

 

2138번: 전구와 스위치

N개의 스위치와 N개의 전구가 있다. 각각의 전구는 켜져 있는 상태와 꺼져 있는 상태 중 하나의 상태를 가진다. i(1 < i < N)번 스위치를 누르면 i-1, i, i+1의 세 개의 전구의 상태가 바뀐다. 즉, 꺼져

www.acmicpc.net

 

 

 

 

 

'[Python] Baekjoon > Greedy(그리디)' 카테고리의 다른 글

[백준(Baekjoon] 11047 동전 0  (0) 2021.12.16
[백준(Baekjoon)] 1080 행렬  (0) 2021.12.14

댓글