Notice
250x250
Recent Posts
Recent Comments
Link
넘치게 채우기
MITM(Meet-in-the-Middle): n <= 40에 대한 Subset Sum 문제를 위한 방법 본문
컴퓨터과학/알고리즘
MITM(Meet-in-the-Middle): n <= 40에 대한 Subset Sum 문제를 위한 방법
riveroverflow 2024. 12. 6. 11:39728x90
반응형
기본적인 브루트 포스 방법은 O(2^n)이 걸린다.
그래서, n=20인 경우에만 시간 효율적으로 사용할 수 있다.
개선해서, n <=40에서 효율적인, O(2^{n/2})인 방법이 존재한다.
MITM, Meet-in-the-Middle알고리즘이다.
n길이의 배열 arr이 주어지고, 합이 s인 부분배열의 개수를 구한다고 해보자.
핵심 아이디어는 다음과 같다:
배열을 절반으로 나눠서, 각각 브루트 포스로 모든 조합을 구한다. 각각 left, right라 한다.
이진탐색을 이용할 것이기에, right를 정렬해준다.
left의 조합들에서 각각 right에서 target = s-leftsum값에 대해 upper_bound(target보다 초과인 큰 요소의 첫 인덱스), lower_bound(target이상인 요소의 첫 인덱스)를 구해서 upper_bound - lower_bound를 구해서 총 개수에 누적한다.
즉, 해당 left의 조합에 대응하는 right의 조합이 upper_bound - lower_bound개 있다는 뜻이다.
코드 - C++
#include <bits/stdc++.h>
using namespace std;
void generateSubsetSums(const vector<int>& arr, vector<int>& subsetSums) {
int size = arr.size();
int numSubsets = 1 << size;
for (int mask = 0; mask < numSubsets; ++mask) {
int sum = 0;
for (int i = 0; i < size; ++i) {
if (mask & (1 << i)) // i번째 요소가 부분 집합에 포함되면
sum += arr[i];
}
subsetSums.push_back(sum);
}
}
int main() {
int n, s;
n = 40, s = 100; // (예시)
vector<int> arr(n);
for(int i = 0; i < n; ++i) {
arr[i] = i;
}
// 배열 나누기
vector<int> leftArr(arr.begin(), arr.begin() + n / 2);
vector<int> rightArr(arr.begin() + n / 2, arr.end());
// 부분 집합 합 계산
vector<int> leftSums, rightSums;
generateSubsetSums(leftArr, leftSums);
generateSubsetSums(rightArr, rightSums);
// 정렬
sort(rightSums.begin(), rightSums.end());
// 이진 탐색으로 대응되는 합 맞춰서 개수 누적
int ans = 0;
for (int leftSum : leftSums) {
int target = s - leftSum;
ans += upper_bound(rightSums.begin(), rightSums.end(), target) -
lower_bound(rightSums.begin(), rightSums.end(), target);
}
cout << ans << "\n";
return 0;
}
728x90
반응형
'컴퓨터과학 > 알고리즘' 카테고리의 다른 글
LIS(Longest Increasing Subsequence) - O(nlogn)으로 진짜 LIS를 구하기 (0) | 2024.10.21 |
---|---|
오일러 경로와 오일러 회로(Eulerian Trail, Eulerian Circuit) (0) | 2024.10.16 |
문자열 패턴 검색: 3 - KMP 알고리즘 (0) | 2024.09.20 |
문자열 패턴 검색: 2 - 라빈-카프 알고리즘 (Rabin-Karp Algorithm) (0) | 2024.09.20 |
문자열 패턴 검색: 1 - Naive 패턴 검색 (Naive Pattern Searching) (0) | 2024.09.20 |