ShovelingLife
A Game Programmer
ShovelingLife
전체 방문자
오늘
어제
  • 분류 전체보기 (1072) N
    • 그래픽스 (57)
      • 공통 (19)
      • 수학 물리 (22)
      • OpenGL & Vulkan (1)
      • DirectX (14)
    • 게임엔진 (183)
      • Unreal (69)
      • Unity (103)
      • Cocos2D-X (3)
      • 개인 플젝 (8)
    • 코딩테스트 (221)
      • 공통 (7)
      • 프로그래머스 (22)
      • 백준 (162)
      • LeetCode (19)
      • HackerRank (2)
      • 코딩테스트 알고리즘 (8)
    • CS (235)
      • 공통 (21)
      • 네트워크 (44)
      • OS & 하드웨어 (55)
      • 자료구조 & 알고리즘 (98)
      • 디자인패턴 (6)
      • UML (4)
      • 데이터베이스 (7)
    • 프로그래밍 언어 (348) N
      • C++ (167)
      • C# (90) N
      • Java (9)
      • Python (33)
      • SQL (30)
      • JavaScript (8)
      • React (7)
    • 그 외 (9)
      • Math (5)
      • 일상 (5)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

  • Source Code 좌측 상단에 복사 버튼 추가 완료
  • 언리얼 엔진 C++ 빌드시간 단축 꿀팁
  • 게임 업계 코딩테스트 관련
  • 1인칭 시점으로 써내려가는 글들

인기 글

태그

  • 문자열
  • 오블완
  • 그래픽스
  • 함수
  • Unity
  • 클래스
  • 배열
  • SQL
  • 백준
  • 유니티
  • 언리얼
  • C++
  • 알고리즘
  • 포인터
  • string
  • C
  • 티스토리챌린지
  • 프로그래머스
  • c#
  • 파이썬

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
ShovelingLife

A Game Programmer

CS/자료구조 & 알고리즘

냅색 - meet in the middle (밋 인 더 미들) 알고리즘

2023. 10. 25. 19:30

n<=40 인 n개의 정수 집합이 있다고 하자. 정수 집합의 부분집합 중 원소의 합이 S 보다 작거나 같은 부분집합 중,

그 합이 최대인 것을 구하라.

 

예제

Input : set[] = {45, 34, 4, 12, 5, 2} and S = 42

Output : 41

부분집합 {34, 5, 2}으로 41을 얻는다.

 

Input : Set[] = {3, 34, 4, 12, 5, 2} and S = 10

Output : 10

부분집합 {2, 3, 5} 으로 10을 얻는다.

 

문제를 전탐색하면 O(2^n)이다. 시간 복잡도가 너무 크다.

Meet in the middle 은 입력이 적당히 작긴 하지만 전탐색은 만만하지 않을 때 쓰는 검색 알고리즘이다.

 

 

분할 정복처럼 부분집합을 두 개로 쪼개고, 각 부분집합을 각각 풀고 병합하지만 완전히 분할 정복처럼 풀 수는 없고, 약간 변형해야 한다.

 

1. 집합을 두 부분집합으로 쪼개고, 부분집합 A, B 라고 합시다. A의 원소는 n/2 개고 B는 나머지가 들어가 있다.

2. A에서 구할 수 있는 모든 부분집합들의 원소의 합을 계산하고, 배열 X에 저장한다. 마찬가지로 B에서 구할 수 있는 모든 부분집합들의 원소의 합을 계산하고, 배열 Y에 저장한다. X와 Y 의 크기는 최대 2^(n/2) 이다.

3. X와 Y을 조합하여 합이 S보다 작은 것을 구한다.

 - 가장 간단한 방법은 X와 Y 의 모든 원소를 순회하면서 조합을 구하는 것이지만, 이것은 O(2^n)이다.

 - 시간복잡도를 줄이기 위해, Y를 정렬하고 X의 각 원소마다 순회한다. Y 에서 이진 탐색을 진행하여, x+y <= S 인 원소 y를 찾는다.

 - 이진 탐색이 시간 복잡도를 줄여 주므로 2^(n/2)log(2^(n/2)) 가 시간복잡도가 된다.

 - 계산하면 최종 시간복잡도는 O(2^(n/2) * n ) 이다.

 

// C++ program to demonstrate working of Meet in the 
// Middle algorithm for maximum subset sum problem. 
#include <bits/stdc++.h> 
using namespace std; 
typedef long long int ll; 
ll X[2000005],Y[2000005]; 

// Find all possible sum of elements of a[] and store 
// in x[] 
void calcsubarray(ll a[], ll x[], int n, int c) 
{ 
	for (int i=0; i<(1<<n); i++) 
	{ 
		ll s = 0; 
		for (int j=0; j<n; j++) 
			if (i & (1<<j)) 
				s += a[j+c]; 
		x[i] = s; 
	} 
} 

// Returns the maximum possible sum less or equal to S 
ll solveSubsetSum(ll a[], int n, ll S) 
{ 
	// Compute all subset sums of first and second 
	// halves 
	calcsubarray(a, X, n/2, 0); 
	calcsubarray(a, Y, n-n/2, n/2); 

	int size_X = 1<<(n/2); 
	int size_Y = 1<<(n-n/2); 

	// Sort Y (we need to do doing binary search in it) 
	sort(Y, Y+size_Y); 

	// To keep track of the maximum sum of a subset 
	// such that the maximum sum is less than S 
	ll max = 0; 

	// Traverse all elements of X and do Binary Search 
	// for a pair in Y with maximum sum less than S. 
	for (int i=0; i<size_X; i++) 
	{ 
		if (X[i] <= S) 
		{ 
			// lower_bound() returns the first address 
			// which has value greater than or equal to 
			// S-X[i]. 
			int p = lower_bound(Y, Y+size_Y, S-X[i]) - Y; 

			// If S-X[i] was not in array Y then decrease 
			// p by 1 
			if (p == size_Y || Y[p] != (S-X[i])) 
				p--; 

			if ((Y[p]+X[i]) > max) 
				max = Y[p]+X[i]; 
		} 
	} 
	return max; 
} 

// Driver code 
int main() 
{ 
	ll a[] = {3, 34, 4, 12, 5, 2}; 
	int n=sizeof(a)/sizeof(a[0]); 
	ll S = 10; 
	printf("Largest value smaller than or equal to given "
		"sum is %lld\n", solveSubsetSum(a,n,S)); 
	return 0; 
}

 

냅색 - meet in the middle :: 세상 끝 조그만 서가 (tistory.com)

저작자표시 (새창열림)

'CS > 자료구조 & 알고리즘' 카테고리의 다른 글

[C++] valarray - 오직 수치값만 저장하는 컨테이너  (0) 2023.11.05
[C#] 우선순위 큐 개념과 힙을 통한 구현  (0) 2023.10.26
Boyer-Moore (보이어무어) 알고리즘 / 문자열 탐색  (0) 2023.10.25
KMP (문자열 중 특정 패턴을 찾아내는 탐색) 알고리즘 C++ 구현  (0) 2023.10.25
페이지 교체 알고리즘  (0) 2023.10.23
    'CS/자료구조 & 알고리즘' 카테고리의 다른 글
    • [C++] valarray - 오직 수치값만 저장하는 컨테이너
    • [C#] 우선순위 큐 개념과 힙을 통한 구현
    • Boyer-Moore (보이어무어) 알고리즘 / 문자열 탐색
    • KMP (문자열 중 특정 패턴을 찾아내는 탐색) 알고리즘 C++ 구현
    ShovelingLife
    ShovelingLife
    Main skill stack => Unity C# / Unreal C++ Studying Front / BackEnd, Java Python

    티스토리툴바