[백준] 1244_스위치 켜고 끄기

김태민·2021년 8월 21일
3

알고리즘

목록 보기
1/77

Mingssssss

1. 문제

2021.08.21

1부터 연속적으로 번호가 붙어있는 스위치들이 있다. 스위치는 켜져 있거나 꺼져있는 상태이다. <그림 1>에 스위치 8개의 상태가 표시되어 있다. ‘1’은 스위치가 켜져 있음을, ‘0’은 꺼져 있음을 나타낸다. 그리고 학생 몇 명을 뽑아서, 학생들에게 1 이상이고 스위치 개수 이하인 자연수를 하나씩 나누어주었다. 학생들은 자신의 성별과 받은 수에 따라 아래와 같은 방식으로 스위치를 조작하게 된다.

남학생은 스위치 번호가 자기가 받은 수의 배수이면, 그 스위치의 상태를 바꾼다. 즉, 스위치가 켜져 있으면 끄고, 꺼져 있으면 켠다. <그림 1>과 같은 상태에서 남학생이 3을 받았다면, 이 학생은 <그림 2>와 같이 3번, 6번 스위치의 상태를 바꾼다.

여학생은 자기가 받은 수와 같은 번호가 붙은 스위치를 중심으로 좌우가 대칭이면서 가장 많은 스위치를 포함하는 구간을 찾아서, 그 구간에 속한 스위치의 상태를 모두 바꾼다. 이때 구간에 속한 스위치 개수는 항상 홀수가 된다.

스위치 번호 ① ② ③ ④ ⑤ ⑥ ⑦ ⑧
스위치 상태 0 1 0 1 0 0 0 1
<그림 1>

예를 들어 <그림 2>에서 여학생이 3을 받았다면, 3번 스위치를 중심으로 2번, 4번 스위치의 상태가 같고 1번, 5번 스위치의 상태가 같으므로, <그림 3>과 같이 1번부터 5번까지 스위치의 상태를 모두 바꾼다. 만약 <그림 2>에서 여학생이 4를 받았다면, 3번, 5번 스위치의 상태가 서로 다르므로 4번 스위치의 상태만 바꾼다.

스위치 번호 ① ② ③ ④ ⑤ ⑥ ⑦ ⑧
스위치 상태 0 1 1 1 0 1 0 1
<그림 2>

스위치 번호 ① ② ③ ④ ⑤ ⑥ ⑦ ⑧
스위치 상태 1 0 0 0 1 1 0 1
<그림 3>

입력으로 스위치들의 처음 상태가 주어지고, 각 학생의 성별과 받은 수가 주어진다. 학생들은 입력되는 순서대로 자기의 성별과 받은 수에 따라 스위치의 상태를 바꾸었을 때, 스위치들의 마지막 상태를 출력하는 프로그램을 작성하시오.

입력
첫째 줄에는 스위치 개수가 주어진다. 스위치 개수는 100 이하인 양의 정수이다. 둘째 줄에는 각 스위치의 상태가 주어진다. 켜져 있으면 1, 꺼져있으면 0이라고 표시하고 사이에 빈칸이 하나씩 있다. 셋째 줄에는 학생수가 주어진다. 학생수는 100 이하인 양의 정수이다. 넷째 줄부터 마지막 줄까지 한 줄에 한 학생의 성별, 학생이 받은 수가 주어진다. 남학생은 1로, 여학생은 2로 표시하고, 학생이 받은 수는 스위치 개수 이하인 양의 정수이다. 학생의 성별과 받은 수 사이에 빈칸이 하나씩 있다.

출력
스위치의 상태를 1번 스위치에서 시작하여 마지막 스위치까지 한 줄에 20개씩 출력한다. 예를 들어 21번 스위치가 있다면 이 스위치의 상태는 둘째 줄 맨 앞에 출력한다. 켜진 스위치는 1, 꺼진 스위치는 0으로 표시하고, 스위치 상태 사이에 빈칸을 하나씩 둔다.

예제 입력 1
8
0 1 0 1 0 0 0 1
2
1 3
2 3
예제 출력 1
1 0 0 0 1 1 0 1

2. 코드

import sys
sys.stdin = open('input.txt')

def switch_on_off(switch_count):

    for i in arr:
        a = 0
        b = 0
        gender = i[0]    # i[0]은 남학생(1)/여학생(2)
        num = i[1]       # num은 입력 숫자
        if gender == 1:  # 남학생일 때,
            for j in range(1, (switch_count//num)+1):  # 배수만큼 range 생성
                if switch[j*num-1] == 1:
                    switch[j * num - 1] = 0
                elif switch[j*num-1] == 0:
                    switch[j * num - 1] = 1

        elif gender == 2: # 여학생일 때,
            for r in range(1, num+1):
                if num-1-r >= 0 and num-1+r < switch_count and switch[num-1-r] == switch[num-1+r]:
                    continue
                elif num-1-r < 0 or num-1+r >= switch_count or switch[num-1-r] != switch[num-1+r]:
                    for y in range(num-r, num-1+r):
                        if switch[y] == 1:
                            switch[y] = 0
                        elif switch[y] == 0:
                            switch[y] = 1
                    break

    for i, e in enumerate(switch):
        if i and not (i % 20):
            print()
        print(e, end=' ')

switch_count = int(input())
switch = list(map(int, input().split()))
std = int(input())
arr = [list(map(int, input().split())) for _ in range(std)]
switch_on_off(switch_count)

3. 리뷰

남학생의 경우 코드 짜는게 어렵지 않았다. 받아온 값에서 인덱스만 유의해서 짜면 됐다.
문제는 여학생의 경우였는데, 문제 이해를 잘못해서 처음에 받아온 num을 포함하여
양 옆의 숫자가 같을 때 바꾸는줄 알고 코드를 짰더니 테스트 케이스 외에는 틀렸다고 나왔다..
woosteel님과 함께 코드 리뷰를 진행하는 도중 문제를 천천히 다시 읽어보니 num 기준으로
양 옆의 숫자만 같으면 조건에 해당되어서 해당 조건을 작성하고, 양쪽 끝에 벽을 쳐서 완성했다.
벽에 도달하면 그 전까지의 인덱스를 확인하여 1이면 0으로, 0이면 1로 숫자를 변환했다.
마지막으로 출력에서도 어려움을 겪었는데, 20개의 스위치까지는 한 줄로 표현하고,
21번째 스위치부터는 줄바꿈을 해서 print 해야 했다. 저 출력 방법은 잘 익혀둬서
나중에도 써먹어야 겠다.

profile
어제보다 성장하는 개발자

2개의 댓글

comment-user-thumbnail
2022년 10월 12일

스위치 끄고 뭐하시게요 ?

1개의 답글