[백준 30237] 합집합 (c++) Codeforces Round 899 (Div. 2) B번

2024. 4. 30. 10:15·PS/백준 알고리즘[BOJ]
728x90

1. 문제

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

코드포스 Round899 B번 문제입니다.

2. 풀이

차집합 계산하기

U = S1 ∪ S2 ∪ S3 ∪ ... ∪ Sn 이라고 해봅시다. 먼저 우리가 구하는 S는 완전탐색으로 생각해볼 수 있습니다. S₁부터 Sn까지 모든 부분집합을 Subset이라고 하면, 모든 Subset에 대해서 U - Subset을 비교하는 방법입니다. 즉,  전체합집합과의 차집합을 비교하는 것으로 생각할 수 있습니다. 하지만 Subset을 모두 탐색하면 O(2ⁿ)이므로 시간초과가 발생합니다.

따라서 전체집합에서 원소를 하나씩 빼보는 방식을 생각했습니다. x ∈ U인 임의의 x에 대해 U - x를계산하면  x를 가지고 있는 모든 Si도 빠져야 합니다. 예를 들어 test case 1을 살펴보겠습니다.

4(입력할 Si의 개수)
3 1 2 3 → S1 = {1, 2, 3}
2 4 5 → S2 = {4, 5}
2 3 4 → S3 = {3, 4}
3 1 4 5 → S4 = {1, 4, 5}

위의 입력에서 U = {1, 2, 3, 4, 5}가 됩니다. 만약 x = 3인경우 차집합 U - x를 고려한다고 하면 3을 포함하는 S1, S3이 모두 빠집니다. 따라서 x = 3인 경우 우리가 구하는 S =  U - (S1 ∪ S3) = S2 ∪ S4가 됩니다.

위처럼 합집합 U를 미리 구해놓고 모든 x에 대해 비교하면  O(Nx)의 시간복잡도로 충분히 해결할 수 있습니다. 마치 U의 집합을 비둘기집처럼 생각하고 원소를 기준으로 탐색하는 비둘기집 원리처럼 생각할 수 있습니다.

 

비트마스킹

집합의 표현방법을 2차원 배열로 해도 되지만 비트마스킹을 이용하면 훨씬 간단하고 빠르게 구현할 수 있습니다. 특히나 합집합, 차집합 등은 |(OR), &(AND)연산을 이용하여 O(1)에 계산할 수 있습니다.

 

3. 구현

비트마스킹을 이용하여 원소마다 차집합을 비교하며 S의 최솟값을 구하는 코드입니다. 다음 몇 가지를 주의해야 합니다.

  • 집합의 원소가 50개이므로 64비트 long long 자료형으로 비트를 표현해야 합니다.
  • 비트이동 과정에서 (1 << k)가 아니라 (1LL << k)처럼 연산 과정에서도 overflow를 신경써야 합니다.
  • test case마다 state, ans 등이 달라지므로 초기화해주어야 합니다.
#include<iostream>
#include<cstring>

using namespace std;

int N, M, T, ans;
long long state[51];

int bitCount(long long x) {
	int ret = 0;
	for (int i = 0; i < 50; i++) {
		ret += (x >> i) & 1;
	}
	return ret;
}

int main(void) {
	cin.tie(0);
	ios_base::sync_with_stdio(0);
	cin >> T;
	while (T--) {
		memset(state, 0, sizeof(state));
		long long Union = 0;

		cin >> N;
		for (int i = 0; i < N; i++) {
			cin >> M;
			for (int j = 0; j < M; j++) {
				long long x;
				cin >> x;
				state[i] |= (1LL << (x -1));
				Union |= (1LL << (x - 1));
			}
		}

		//solve
		ans = 0;
		for (int i = 0; i < 50; i++) {
			long long cmb = 0;
			long long x = (1LL << i);
			for (int j = 0; j < N; j++) {
				if (x & state[j]) continue;
				cmb |= state[j];
			}
			int cmb_siz = bitCount(cmb);
			int Union_siz = bitCount(Union);
			if (cmb_siz < Union_siz) ans = max(ans, cmb_siz);
			//else ans = 0;
		}
		cout << ans << "\n";
	}
}
728x90
저작자표시 비영리 변경금지 (새창열림)

'PS > 백준 알고리즘[BOJ]' 카테고리의 다른 글

[BOJ] 2178 미로 탐색 (C++)  (1) 2025.07.09
[백준 1562] 계단수 (C++)  (0) 2024.04.19
[백준 10844] 쉬운 계단 수 (C++)  (0) 2024.04.18
[백준 1043] 거짓말 (C++)  (0) 2024.04.08
[백준 11399] ATM (C++)  (0) 2024.03.20
'PS/백준 알고리즘[BOJ]' 카테고리의 다른 글
  • [BOJ] 2178 미로 탐색 (C++)
  • [백준 1562] 계단수 (C++)
  • [백준 10844] 쉬운 계단 수 (C++)
  • [백준 1043] 거짓말 (C++)
BE_개발자
BE_개발자
경이로운 BE 개발자가 되기 위한 프로그래밍 공부 기록장
    250x250
  • BE_개발자
    경이로운 개발일기
    BE_개발자
  • 전체
    오늘
    어제
    • 전체 보기 (213)
      • AI (1)
        • AI native (0)
        • Skill (0)
      • SpringBoot (4)
        • JPA (3)
        • Security (0)
        • 튜토리얼 (1)
        • 기타 (0)
      • Infra (0)
        • Docker (0)
        • AWS (0)
        • NCP (0)
        • GCP (0)
      • React (19)
      • 서버 (0)
      • Computer Science (16)
        • SW Engineering (10)
        • Data Base (2)
        • OS(운영 체제) (4)
      • Data science (0)
        • Probability & Random Variab.. (0)
        • Data Analysis(데이터 분석) (0)
      • 자료구조 | 알고리즘 (57)
        • 선형 자료구죠 (6)
        • 비선형 자료구조 (9)
        • 정렬(Sort) (3)
        • 탐색(Brute Force) (7)
        • 분할 정복(Devide Conquer) (3)
        • 동적 계획법 (6)
        • 탐욕(Greedy) (2)
        • 수학 (7)
        • 심화 알고리즘 (10)
      • PS (44)
        • 백준 알고리즘[BOJ] (38)
        • 프로그래머스[programmers] (3)
      • Dev tool (15)
        • 개발 도구 및 환경 (0)
        • vscode (3)
        • Git Hub (4)
        • Chrome 웹스토어 (5)
        • Python 전용 개발환경 (0)
      • 성장기록 (1)
      • 개인 project (14)
        • 홈페이지 만들기 (11)
        • 냉보미 (1)
      • STL(Standard Library) (9)
      • programming Language (1)
        • javascript (1)
      • 기타 (13)
        • html css (11)
      • (책, 글, 블로그)리뷰 (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 백준
    • Github
    • Notion
    • 서울과학기술대학교 학술동아리 EC
  • 공지사항

  • 인기 글

  • 태그

    백준
    PS
    탐색
    스택
    프론트엔드
    stl
    C++
    그리디
    CS
    비트마스킹
    알고리즘
    브루트포스
    react
    운영체제
    스프링부트
    SW 공학
    괄호쌍
    분할정복
    백트래킹
    OS
    재귀함수
    DP
    수학
    stack
    자료구조
    이분 탐색
    BFS
    SW Engineering
    완전 탐색
    순열
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
BE_개발자
[백준 30237] 합집합 (c++) Codeforces Round 899 (Div. 2) B번
상단으로

티스토리툴바