혼자 정리

11723번: 집합 본문

알고리즘 문풀/백준

11723번: 집합

tbonelee 2021. 7. 16. 12:33

문제링크

CPP 코드

#include <iostream>
#include <cstring>

using namespace std;

int M;
int S;
string cmd, num;

void do_add(int &S)
{
    cin >> num;
    S |= (1 << (atoi(num.c_str()) - 1));
}

void do_remove(int &S)
{
    cin >> num;
    S &= ~(1 << (atoi(num.c_str()) - 1));
}

void do_check(int &S)
{
    cin >> num;
    if ((S & (1 << (atoi(num.c_str()) - 1))) > 0)
        cout << "1\n";
    else
        cout << "0\n";
}

void do_toggle(int &S)
{
    cin >> num;
    if ((S & (1 << (atoi(num.c_str()) - 1))) > 0)
    {
        S &= ~(1 << (atoi(num.c_str()) - 1));
    }
    else
    {
        S |= (1 << (atoi(num.c_str()) - 1));
    }
}

void do_all(int &S)
{
    S |= 0b11111111111111111111;
}

void do_empty(int &S)
{
    S &= 0;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);

    S = 0;
    cin >> M;
    for (int i = 1; i <= M; i++)
    {
        cin >> cmd;
        if (strcmp(cmd.c_str(), "add") == 0)
            do_add(S);
        else if (strcmp(cmd.c_str(), "remove") == 0)
            do_remove(S);
        else if (strcmp(cmd.c_str(), "check") == 0)
            do_check(S);
        else if (strcmp(cmd.c_str(), "toggle") == 0)
            do_toggle(S);
        else if (strcmp(cmd.c_str(), "all") == 0)
            do_all(S);
        else
            do_empty(S);
    }
}

어제 해시맵을 사용했던 터라 이번에도 해시맵으로 풀면 되나 했다(키-밸류 느낌이 들어서).
하지만 키의 갯수가 한정되어 있고 1부터 20까지 순차적으로 정해져있기 때문에 비트마스킹을 통해 풀 수 있겠다고 생각하고 처음으로 비트마스킹을 시도해보았다.

파이썬 코드

import sys
input = sys.stdin.readline

S = 0
M = int(input())
for i in range(1, M+1):
    arr = input().split()
    if arr[0] == 'add':
        S |= (1 << (int(arr[1]) - 1))
    elif arr[0] == 'remove':
        S &= ~(1 << (int(arr[1]) - 1))
    elif arr[0] == 'check':
        print(1 if (S & (1 << (int(arr[1]) - 1))) > 0 else 0)
    elif arr[0] == 'toggle':
        if S & (1 << (int(arr[1]) - 1)) > 0:
            S &= ~(1 << (int(arr[1]) - 1))
        else:
            S |= (1 << (int(arr[1]) - 1))
    elif arr[0] == 'all':
        S |= 0b11111111111111111111
    elif arr[0] == 'empty':
        S &= 0

같은 로직으로 파이썬으로 짜보았다.
파이썬은 print문 안에서 조건문을 사용할 수 있더라. 대신에 if문 전에 실행문이 나와야 된다는 점에 유의하자. 다중 if문도 가능하다고 한다.
input().split()을 통해 변수에 리스트로 넣어줄 수 있다. c나 cpp처럼 복잡하게 배열이나 벡터 선언 고민할 필요가 없는 점에서는 좋은 것 같다. 대신 여기서도 out of range를 참조하려 하면 문제가 생기니 주의하자.

다른 분들 풀이를 보니 'add', 'remove', 'toggle'에서 다음과 같이 작성하신 분들도 있었다.

...
  else:
    a = 1 << int(l[1]) - 1
    if (l[0] == 'add' and s & a == 0) or (l[0] == 'remove' and s & a) or l[0] == 'toggle':
      s ^= a

어떤 비트 k에 비트 1에 대해 xor연산을 수행하면 1) k가 1이면(있으면) 0, 2) k가 0이면(없으면) 1이 되므로 자연스럽게 토글이 된다.
다음에 비트를 바꿔주는 연산이 필요하게 되면 비트 1에 대해 xor연산을 써보도록 하자.
또 비슷하게 add명령 또한 비트가 0일때만으로 조건을 걸어주면 비트 1에 대한 xor연산으로 쓸 수 있고, remove 명령도 마찬가지.
따라서 세 가지 명령을 하나의 비트 연산으로 통일시킬 수 있게 된다.

'알고리즘 문풀 > 백준' 카테고리의 다른 글

11726번: 2×n 타일링  (0) 2021.07.19
9095번: 1, 2, 3 더하기  (0) 2021.07.18
17626번: Four Squares  (0) 2021.07.17
1620번: 나는야 포켓몬 마스터 이다솜  (0) 2021.07.15
5525번: IOIOI  (0) 2021.07.15