기타/백준일지
[프로그래머스] 후보키
민지기il
2025. 4. 14. 22:31
#include <bits/stdc++.h>
#define fastio cin.tie(0)->sync_with_stdio(0)
using namespace std;
vector<int> candidates; // 이미 검사한 후보키를 등록
bool isSubset(int target, int previous){
return ((target & previous) == previous); // 포함되는지
}
bool check_minimality(int target){
for(int previous : candidates){
if(isSubset(target, previous))
return false;
}
return true;
}
bool check_uniqueness(int i, vector<vector<string>> relation){
int k = relation[0].size();
vector<string> combined;
for(auto v: relation){
string temp ="";
for (int j=0; j<k; j++)
if((i&(1<<j)) !=0 )
temp+=v[j];
if(find(combined.begin(), combined.end(), temp) != combined.end())
return false;
else
combined.push_back(temp);
}
return true;
}
int solution(vector<vector<string>> relation){
int k=relation[0].size();
for(int i=1; i<(1<<k); i++){
if(check_uniqueness(i, relation) && check_minimality(i))
candidates.push_back(i);
}
int answer = candidates.size();
return answer;
}
<참고>
https://mingyum119.tistory.com/225
<풀이>
비트 마스크
비트마스크 i는 어떤 열들을 선택할지를 이진수로 표현한다.
k는 열의 개수이고 v = {"minji", "22", "seoul"}일 때 i=5이면 2진수로 101 이니까 temp 값이 "minjiseoul"이 되는 것이다
이렇게 유일성과 최소성을 맞춰서 조합을 찾는다.
i & (1<<j): i의 j번째 비트를 검사하는것
1<<j: 1을 왼쪽으로 j칸 이동함
find는 찾으면 그 위치의 iterator를 반환하고 못 찾으면 end를 반환함
isSubset 함수
: 비트마스크로 표현된 두 집합 target과 previous가 있을 때, previous가 target의 부분집합인지 확인한다.
&연산을 통해 1인 비트만 남긴다.
예 1) target = 0111 (A, B, C), previous = 0011 (A, B)
→ 0111 & 0011 = 0011
→ previous는 target의 부분집합이다
예 2) target = 0101 (A, C), previous = 0011 (A, B)
→ 0101 & 0011 = 0001
→ B가 빠졌으므로 부분집합 아님