- 비트 연산자
AND 연산 a & b
OR 연산 a | b
XOR 연산 a ^ b
NOT 연산 ~a
a를 왼쪽으로 b만큼 시프트 a<<b
a를 오른쪽으로 b만큼 시프트 a>>b
- 유의할 점
1) 연산자 우선 순위
비트 연산자는 == , != 보다 우선순위가 낮다.
그래서 if(a&b==4) 같은 코드는 주의! if((a&b)==4)처럼 무조건 괄호를 사용해주는게 좋다.
2) 64비트 오버 플로우
unsinged long long a = (1<<35);
1은 부호 있는 32 bit로 취급 되기 때문에 오버플로우 발생.
따라서 접미사 ull을 붙이거나 unsingd long long tmp = 1 에 저장해서 사용한다.
- 비트 마스크를 이용한 집합 구현
1)공집합
1<<N : N개의 비트를 사용할때 N개의 비트를 모두 0으로 초기화(N+1번째 비트는 )
2)꽉찬 집합
(1<<N) - 1 : N개의 비트를 사용할때 N개의 비트를 모두 1로 초기화
3)합집합(OR)
added = (a | b);
4)교집합(AND)
intersection = (a&b);
5)차집합
removed = (a & ~b);
6)모든 부분집합 순회하기
for(int subset = set; subset>0 ; subset = ((subset-1)&subset) )
{
//모든 부분집합 원소
//subset -1 & subset을 했을 때 최하위 비트가 하나씩 꺼짐(0)
}
예제 문제
https://algospot.com/judge/submission/detail/550178
#include<stdio.h>
#include<algorithm>
using namespace std;
const int INF = 987654321;
int N,K,M,L;
int cache[10][1<<12];
int pre[12];
int classes[10];
int numOfCount(int currentTaken){
int ret = 0;
for(int i=0;i<N;i++){
if((currentTaken>>i)&1)
ret++;
}
return ret;
}
int sol(int currentSemester,int currentTaken){
//printf("currentTaken :%d\n",currentTaken);
if(numOfCount(currentTaken)>=K)
return 0;
if(currentSemester == M)
return INF;
int &ret = cache[currentSemester][currentTaken];
if(ret!=-1)
return ret;
ret = INF;
//이번학기 안듣고 넘김
ret = min(ret, sol(currentSemester+1, currentTaken));
//모든 경우의 수를 고려해서 수업을 들음
int canTake = (classes[currentSemester] & (~currentTaken));//들었던 수업 빼기
//선행수업 조건 안되는 과목 빼기
for(int i=0;i<N;i++){
if(((currentTaken & pre[i]) != pre[i])
&& (canTake&(1<<i))){
canTake &= ~(1<<i);
}
}
for(int take=canTake;take>0;take=((take-1)&canTake)){
if(numOfCount(take)>L)
continue;
ret = min(ret,sol(currentSemester+1, currentTaken|take)+1);
}
return ret;
}
int main(void){
int T;
scanf("%d",&T);
for(int testCase=0;testCase<T;testCase++){
for(int i=0;i<10;i++){
for(int j=0;j<(1<<12);j++){
cache[i][j]=-1;
}
}
scanf("%d %d %d %d",&N,&K,&M,&L);
//set pre classes
for(int n=0;n<N;n++){
int numOfPre;
pre[n] = 0;
scanf("%d",&numOfPre);
for(int cnt=0;cnt<numOfPre;cnt++){
int preClass;
scanf("%d",&preClass);
pre[n] |= (1<<preClass);
}
}
//set semester
for(int m=0;m<M;m++){
int numOfClass;
classes[m] = 0;
scanf("%d",&numOfClass);
for(int cnt=0;cnt<numOfClass;cnt++){
int major;
scanf("%d",&major);
classes[m] |= (1<<major);
}
}
int ret = sol(0,0);
if(ret==INF)
printf("IMPOSSIBLE\n");
else
printf("%d\n",ret);
}
return 0;
}
'알고리즘' 카테고리의 다른 글
[알고리즘 문제해결전략] CLOCKSYNC - 시계 맞추기 (0) | 2022.07.10 |
---|---|
[알고리즘 문제해결전략] BOARDCOVER - 게임판 덮기 (0) | 2022.07.03 |
[알고리즘 문제해결전략] PICNIC - 소풍 (0) | 2022.06.19 |
[알고리즘 문제해결전략] BOGGLE - 보글 게임 (0) | 2022.06.19 |
[무식하게 풀기 - 재귀] N개의 원소중 M개를 고르는 모든 조합 찾는 방법 (0) | 2020.02.22 |