알고리즘 배낭문제
배낭 문제
배낭 문제란 무게와 이익이 있는 물건들을 용량이 정해진 배낭에 넣으려고 할 때 최대의 이익을 얻으려면 어떤 물건들을 넣어야 할까를 결정하는 조합 최적화 문제이다.
배낭 문제는 두가지 유형이 있다.
-
부분 배낭 문제
물건을 쪼개서 담을 수 있는 경우 욕심쟁이 방법으로 해결 가능하다.
-
0-1배낭 문제
물건을 쪼개서 담을 수 없는 경우 욕심쟁이 방법으로 해결 불가능하다.
배낭 문제 정의
- n개의 물건 S={object1, object2, …,objectn}
- 각 물건의 무게 W={w1, w2, …, wn} w는 양의 정수
- 각 물건의 이익 P={p1, p2, … pn} p는 양의 정수
- 각 물건이 배낭에 넣어지는 부분 X={x1, x2, …xn}
0<=xi<=1
- 배낭 용량 M은 양의 정수
- 배낭 문제의 최적해는 모든 물건 pnxn 합의 최대값, 단 모든 물건 wixi의 합은 M보다 작다(배낭을 찢으면 안됀다.)
해법
단위무게 당 이익이 큰 것부터 먼저 배낭에 집어넣는다. 다 들어갈 때까지 넣다가 안들거나는 무게의 물건을 만나게 되면 이 물건을 남은 공간만큼 쪼개어 담는다.
float frac_ks_GM(int M, int w[], int P[], float X[], int n)
{
int i;
float max_profit = 0;
sort(W, P, n);
for(i = 1; i <= n; i++) x[i] = 0;
for(i = 1; i <= n; i++)
{
if(W[i] > M) break;
X[i] = 1;
M = M - W[i];
}
if(i <= n) X[i] = (float) M/W[i];
for(i = 1; i <= n; i++) max_profit += p[i]* X[i];
return max_profit;
}
최적 부분 구조
-
부분 배낭 문제
최적해인 상태의 배낭에서 임의의 i번째 물건을 z만큼 남겨두고 배낭을 비워 원위치 시키자. 이 상태에서 다시 배낭의 최대 이익을 얻도록 물건을 집어 넣는다면 배낭에서 비워진 물건들이 그 무게 그대로 배낭에 다시 들어가게 된다. 배낭 용량 M과 물건 무게 W={..,wi,..}에 대한 최적해는 배낭 용량 M-z과 물건 무게 W={..,wi-z,…}에 대한 최적해 보다 pi*(z/wi)만큼 더 큼 따라서 최적 부분 구조를 가짐
-
0-1 배낭 문제
역시 같은 이유로 최적 부분 구조를 가지지만 최적해는 얻을 수 없다!