C++에서는 <<(왼쪽 시프트)와 >>(오른쪽 시프트) 연산자를 사용
1 << n
#include <iostream>
using namespace std;
int main() {
cout << (1 << 0) << endl; // 1 (2^0)
cout << (1 << 1) << endl; // 2 (2^1)
cout << (1 << 2) << endl; // 4 (2^2)
cout << (1 << 3) << endl; // 8 (2^3)
cout << (1 << 4) << endl; // 16 (2^4)
return 0;
}
1
2
4
8
16
💡 즉, 1 << n은 2^n과 같은 의미!
1 << 3 // 1을 왼쪽으로 3칸 이동
0000 0001 (1) → 0000 1000 (8, 즉 2^3)
n >> m
#include <iostream>
using namespace std;
int main() {
cout << (16 >> 1) << endl; // 8 (16 / 2^1)
cout << (16 >> 2) << endl; // 4 (16 / 2^2)
cout << (16 >> 3) << endl; // 2 (16 / 2^3)
cout << (16 >> 4) << endl; // 1 (16 / 2^4)
return 0;
}
8
4
2
1
16 >> 3 // 16을 오른쪽으로 3칸 이동
0001 0000 (16) → 0000 0010 (2, 즉 16 / 2^3)
연산 의미 예제 결과
1 << n | 2^n 배 증가 | 1 << 4 | 16 |
n >> m | 2^m 배 감소 | 16 >> 2 | 4 |
int a = 5;
int b = a << 3; // a * 2^3 = 5 * 8 = 40
int c = a >> 2; // a / 2^2 = 5 / 4 = 1
💡 왼쪽 시프트(<<)는 곱셈, 오른쪽 시프트(>>)는 나눗셈과 같은 역할!
비트 연산을 이용하여 어떤 숫자가 포함되었는지 검사할 수 있습니다.
int mask = (1 << 3); // 3번째 비트만 켜짐 (0000 1000)
int num = 10; // 10 = 1010
if (num & mask) {
cout << "3번째 비트가 켜져 있습니다." << endl;
} else {
cout << "3번째 비트가 꺼져 있습니다." << endl;
}
💡 비트 AND (&) 연산을 이용하면 특정 비트가 켜져 있는지 쉽게 확인 가능!
비트 시프트 연산은 비트마스크 (Bitmask) 알고리즘에서도 많이 사용됩니다.
예를 들어, 4개의 도시 방문 상태를 저장할 때:
비트마스크를 사용할 경우, 특정 도시를 방문할 때:
int visited = 0; // 0000 (모든 도시 방문 X)
visited |= (1 << 2); // 2번 도시 방문 (0010)
visited |= (1 << 3); // 3번 도시 방문 (1010)
💡 비트 연산을 사용하면 방문 상태를 효율적으로 저장하고 관리할 수 있음!
✅ 1 << n → 2^n을 계산하는 빠른 방법
✅ n >> m → n / 2^m을 계산하는 빠른 방법
✅ 비트마스크와 함께 사용하여 효율적인 상태 관리 가능
✅ TSP(외판원 문제), 그래프 문제, 비트마스크 DP에서 많이 활용됨!
#define MAX_N 16
int n, dp[MAX_N][1 << MAX_N], dist[MAX_N][MAX_N];
1<<16=216=655361 << 16 = 2^{16} = 65536
즉, 1 << MAX_N은 2의 MAX_N 승을 의미
int dp[MAX_N][1 << MAX_N];
이 배열은 TSP(외판원 문제, Traveling Salesman Problem) 또는 비트마스크 DP에서 자주 사용
표현 의미
dp[i][j] | i번째 도시까지 방문했을 때, 방문 상태가 j일 때의 최소 비용 |
📌 dp[MAX_N][MAX_N]과 dp[MAX_N][1 << MAX_N]의 차이점은 배열의 크기와 의미가 다르다는 점
표현 의미
dp[MAX_N][MAX_N] | 최대 16 x 16 크기의 2차원 배열 |
dp[MAX_N][1 << MAX_N] | 16 x 65536 크기의 비트마스크 DP 테이블 |
비트마스크 방문한 도시
0000 (0) | 아무 도시도 방문 X |
0001 (1) | 0번 도시 방문 |
0010 (2) | 1번 도시 방문 |
0011 (3) | 0번, 1번 도시 방문 |
0101 (5) | 0번, 2번 도시 방문 |
1111 (15) | 0~3번 도시 방문 (완전 탐색 완료) |
💡 따라서, dp[i][bitmask]는 i번째 도시에서 현재 방문 상태(bitmask)일 때 최소 비용을 저장하는 DP 테이블
int dist[MAX_N][MAX_N];
📌 dp[MAX_N][1 << MAX_N] vs dp[MAX_N][MAX_N] 비교
표현 의미 크기 용도
dp[MAX_N][MAX_N] | i번 도시에서 j번 도시로 가는 경우 저장 | 16 x 16 | 단순 DP |
dp[MAX_N][1 << MAX_N] | i번 도시까지 방문했을 때, 방문 상태(bitmask)를 저장 | 16 x 65536 | 비트마스크 DP (TSP 문제) |
📌 즉, 이 구조는 TSP(외판원 문제)에서 "방문한 상태를 효율적으로 저장하고 관리"하는데 사용
✔ 1 << MAX_N는 2의 거듭제곱 (2^16 = 65536)
✔ dp[MAX_N][1 << MAX_N]은 비트마스크를 사용하여 방문 상태를 저장하는 DP 테이블
✔ dp[MAX_N][MAX_N]은 단순한 2차원 DP 테이블
✔ dist[MAX_N][MAX_N]은 도시 간 이동 거리 저장용 배열
✔ dp[MAX_N][1 << MAX_N]을 사용하면 모든 방문 상태를 효율적으로 탐색 가능 (TSP 해결에 사용)
🚀 DFS와 BFS의 차이점! (0) | 2025.03.02 |
---|---|
배열 출력하는 방법🚀 (0) | 2025.03.01 |
조합과 순열//combination vs permutation (0) | 2025.02.11 |
트리 vs 그래프 (0) | 2025.01.23 |
이분 탐색 //(Binary Search) (0) | 2025.01.22 |