반응형

https://www.acmicpc.net/problem/11723

 

11723번: 집합

첫째 줄에 수행해야 하는 연산의 수 M (1 ≤ M ≤ 3,000,000)이 주어진다. 둘째 줄부터 M개의 줄에 수행해야 하는 연산이 한 줄에 하나씩 주어진다.

www.acmicpc.net

문제 설명

비어있는 공집합 S가 주어졌을 때, 아래 연산을 수행하는 프로그램을 작성하시오.

  • add x: S에 x를 추가한다. (1 ≤ x ≤ 20) S에 x가 이미 있는 경우에는 연산을 무시한다.
  • remove x: S에서 x를 제거한다. (1 ≤ x ≤ 20) S에 x가 없는 경우에는 연산을 무시한다.
  • check x: S에 x가 있으면 1을, 없으면 0을 출력한다. (1 ≤ x ≤ 20)
  • toggle x: S에 x가 있으면 x를 제거하고, 없으면 x를 추가한다. (1 ≤ x ≤ 20)
  • all: S를 {1, 2, ..., 20} 으로 바꾼다.
  • empty: S를 공집합으로 바꾼다. 

풀이 과정

이 문제는 파이썬의 집합 set을 이용해 단순 구현으로 풀 수도 있고

비트마스크를 이용해 풀 수도 있다.

 

단순 구현방식은 단순히 구현만 하면 되므로, 비트마스크를 이용한 풀이를 소개하려고 한다.

 

집합 내에 속한 1부터 20까지의 숫자를

비트의 각 자리로 매칭시키자.

 

예를 들어, {1, 2, 5, 6} 이라면

110011 로 표기함으로써 1, 2, 5, 6번째에만 1을 넣어주어 집합에 포함되어 있는 수를 표현할 수 있다.

 

그래서 문제에서 주어진 연산은 다음과 같이 구현할 수 있다.

  • all : 1부터 20까지의 자리에 1을 넣어준다.
  • empty : 비트의 모든 자리를 0으로 만든다.
  • add : 비트의 해당 자리를 1로 만든다.
  • remove : 비트의 해당 자리를 0으로 만든다.
  • check : 비트의 해당자리가 1인지 0인지 확인한다.
  • toggle : 비트의 해당 자리 수를 바꾼다 ( 1 ->0 / 0 -> 1 )
import sys

m = int(sys.stdin.readline())

bit = 0
for i in range(m):
    comm = sys.stdin.readline().rstrip().split()

    if comm[0] == "all":
        bit = (1 << 20) - 1
    elif comm[0] == "empty":
        bit = 0
    else:
        op = comm[0]
        num = int(comm[1]) - 1

        if op == "add":
            bit |= (1 << num)
        elif op == "remove":
            bit &= ~(1 << num)
        elif op == "check":
            if bit & (1 << num) == 0:
                print(0)
            else:
                print(1)

        elif op == "toggle":
            bit = bit ^ (1 << num)

 

https://github.com/HongEunho

전체 문제 & 코드는 위의 깃에 정리되어 있습니다.

팔로우 & 맞팔은 환영입니다 !

반응형

'Algorithm > BitMasking' 카테고리의 다른 글

[백준] 1094 막대기 (Python 파이썬)  (0) 2021.09.12
반응형

https://www.acmicpc.net/problem/1094

 

1094번: 막대기

지민이는 길이가 64cm인 막대를 가지고 있다. 어느 날, 그는 길이가 Xcm인 막대가 가지고 싶어졌다. 지민이는 원래 가지고 있던 막대를 더 작은 막대로 자른다음에, 풀로 붙여서 길이가 Xcm인 막대

www.acmicpc.net

문제 설명

지민이는 길이가 64cm인 막대를 가지고 있다. 어느 날, 그는 길이가 Xcm인 막대가 가지고 싶어졌다. 지민이는 원래 가지고 있던 막대를 더 작은 막대로 자른다음에, 풀로 붙여서 길이가 Xcm인 막대를 만들려고 한다.

막대를 자르는 가장 쉬운 방법은 절반으로 자르는 것이다. 지민이는 아래와 같은 과정을 거쳐서 막대를 자르려고 한다.

  1. 지민이가 가지고 있는 막대의 길이를 모두 더한다. 처음에는 64cm 막대 하나만 가지고 있다. 이때, 합이 X보다 크다면, 아래와 같은 과정을 반복한다.
    1. 가지고 있는 막대 중 길이가 가장 짧은 것을 절반으로 자른다.
    2. 만약, 위에서 자른 막대의 절반 중 하나를 버리고 남아있는 막대의 길이의 합이 X보다 크거나 같다면, 위에서 자른 막대의 절반 중 하나를 버린다.
  2. 이제, 남아있는 모든 막대를 풀로 붙여서 Xcm를 만든다.

X가 주어졌을 때, 위의 과정을 거친다면, 몇 개의 막대를 풀로 붙여서 Xcm를 만들 수 있는지 구하는 프로그램을 작성하시오. 


풀이 과정

문제에서 장황하게 설명하고 있는 내용은 결국

입력값을 이진수로 바꿨을 때 1의 갯수 를 묻는 것이므로 비트마스킹으로 접근할 수 있다.

 

단순 구현으로 풀 수도 있지만,

비트마스크를 이용한다면 정말 간편하게 문제를 해결할 수 있다.

 

처음 막대의 길이는 64이고

이를 계속 절반씩 자르게 된다.

 

그럼 가능한 막대는 1, 2, 4, 8, 16, 32, 64가 될 것인데

이들은 모두 2의 0승부터 2의 6승까지 모두 2의 배수로 나타낼 수 있는 수 이다.

 

문제에서, 필요한 막대의 갯수를 물었기 때문에

결국에는 내가 입력한 수를 이진수로 변환했을 때, 1이 몇개가 있는지를 구하면 되는 것이다.

 

즉, 입력값이 23이라면 10111이 되며 1이 4개가 포함되어 있으므로 정답은 4가 될 것이다.

그리고 이는, 길이가 1, 2, 4, 16 짜리 막대들로 23짜리 막대를 만들 수 있다는 뜻이 된다.

x = int(input())

cnt = 0

while x > 0:
    if x & 1:
        cnt += 1

    x >>= 1

print(cnt)

 

https://github.com/HongEunho

전체 문제 & 코드는 위의 깃에 정리되어 있습니다.

팔로우 & 맞팔은 환영입니다 !

반응형

'Algorithm > BitMasking' 카테고리의 다른 글

[백준] 11723 집합 (파이썬 비트마스크)  (0) 2021.09.12

+ Recent posts